xref: /freebsd/sys/dev/mpi3mr/mpi3mr.c (revision 3f3a15543a6721100dda0e4219eb48ecbe35731a)
12d1d418eSSumit Saxena /*
22d1d418eSSumit Saxena  * SPDX-License-Identifier: BSD-2-Clause
32d1d418eSSumit Saxena  *
4945c3ce4SChandrakanth patil  * Copyright (c) 2016-2024, Broadcom Inc. All rights reserved.
52d1d418eSSumit Saxena  * Support: <fbsd-storage-driver.pdl@broadcom.com>
62d1d418eSSumit Saxena  *
72d1d418eSSumit Saxena  * Authors: Sumit Saxena <sumit.saxena@broadcom.com>
82d1d418eSSumit Saxena  *	    Chandrakanth Patil <chandrakanth.patil@broadcom.com>
92d1d418eSSumit Saxena  *
102d1d418eSSumit Saxena  * Redistribution and use in source and binary forms, with or without
112d1d418eSSumit Saxena  * modification, are permitted provided that the following conditions are
122d1d418eSSumit Saxena  * met:
132d1d418eSSumit Saxena  *
142d1d418eSSumit Saxena  * 1. Redistributions of source code must retain the above copyright notice,
152d1d418eSSumit Saxena  *    this list of conditions and the following disclaimer.
162d1d418eSSumit Saxena  * 2. Redistributions in binary form must reproduce the above copyright notice,
172d1d418eSSumit Saxena  *    this list of conditions and the following disclaimer in the documentation and/or other
182d1d418eSSumit Saxena  *    materials provided with the distribution.
192d1d418eSSumit Saxena  * 3. Neither the name of the Broadcom Inc. nor the names of its contributors
202d1d418eSSumit Saxena  *    may be used to endorse or promote products derived from this software without
212d1d418eSSumit Saxena  *    specific prior written permission.
222d1d418eSSumit Saxena  *
232d1d418eSSumit Saxena  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
242d1d418eSSumit Saxena  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
252d1d418eSSumit Saxena  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
262d1d418eSSumit Saxena  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
272d1d418eSSumit Saxena  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
282d1d418eSSumit Saxena  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
292d1d418eSSumit Saxena  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
302d1d418eSSumit Saxena  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
312d1d418eSSumit Saxena  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
322d1d418eSSumit Saxena  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
332d1d418eSSumit Saxena  * POSSIBILITY OF SUCH DAMAGE.
342d1d418eSSumit Saxena  *
352d1d418eSSumit Saxena  * The views and conclusions contained in the software and documentation are
362d1d418eSSumit Saxena  * those of the authors and should not be interpreted as representing
372d1d418eSSumit Saxena  * official policies,either expressed or implied, of the FreeBSD Project.
382d1d418eSSumit Saxena  *
392d1d418eSSumit Saxena  * Mail to: Broadcom Inc 1320 Ridder Park Dr, San Jose, CA 95131
402d1d418eSSumit Saxena  *
412d1d418eSSumit Saxena  * Broadcom Inc. (Broadcom) MPI3MR Adapter FreeBSD
422d1d418eSSumit Saxena  */
432d1d418eSSumit Saxena 
442d1d418eSSumit Saxena #include <sys/types.h>
452d1d418eSSumit Saxena #include <sys/param.h>
462d1d418eSSumit Saxena #include <sys/systm.h>
472d1d418eSSumit Saxena #include <sys/kernel.h>
482d1d418eSSumit Saxena #include <sys/module.h>
492d1d418eSSumit Saxena #include <sys/bus.h>
502d1d418eSSumit Saxena #include <sys/conf.h>
512d1d418eSSumit Saxena #include <sys/malloc.h>
522d1d418eSSumit Saxena #include <sys/sysctl.h>
532d1d418eSSumit Saxena #include <sys/uio.h>
542d1d418eSSumit Saxena 
552d1d418eSSumit Saxena #include <machine/bus.h>
562d1d418eSSumit Saxena #include <machine/resource.h>
572d1d418eSSumit Saxena #include <sys/rman.h>
582d1d418eSSumit Saxena 
592d1d418eSSumit Saxena #include <dev/pci/pcireg.h>
602d1d418eSSumit Saxena #include <dev/pci/pcivar.h>
612d1d418eSSumit Saxena #include <dev/pci/pci_private.h>
622d1d418eSSumit Saxena 
632d1d418eSSumit Saxena #include <cam/cam.h>
642d1d418eSSumit Saxena #include <cam/cam_ccb.h>
652d1d418eSSumit Saxena #include <cam/cam_debug.h>
662d1d418eSSumit Saxena #include <cam/cam_sim.h>
672d1d418eSSumit Saxena #include <cam/cam_xpt_sim.h>
682d1d418eSSumit Saxena #include <cam/cam_xpt_periph.h>
692d1d418eSSumit Saxena #include <cam/cam_periph.h>
702d1d418eSSumit Saxena #include <cam/scsi/scsi_all.h>
712d1d418eSSumit Saxena #include <cam/scsi/scsi_message.h>
722d1d418eSSumit Saxena #include <cam/scsi/smp_all.h>
732d1d418eSSumit Saxena #include <sys/queue.h>
742d1d418eSSumit Saxena #include <sys/kthread.h>
752d1d418eSSumit Saxena #include "mpi3mr.h"
762d1d418eSSumit Saxena #include "mpi3mr_cam.h"
772d1d418eSSumit Saxena #include "mpi3mr_app.h"
782d1d418eSSumit Saxena 
792d1d418eSSumit Saxena static void mpi3mr_repost_reply_buf(struct mpi3mr_softc *sc,
802d1d418eSSumit Saxena 	U64 reply_dma);
812d1d418eSSumit Saxena static int mpi3mr_complete_admin_cmd(struct mpi3mr_softc *sc);
822d1d418eSSumit Saxena static void mpi3mr_port_enable_complete(struct mpi3mr_softc *sc,
832d1d418eSSumit Saxena 	struct mpi3mr_drvr_cmd *drvrcmd);
842d1d418eSSumit Saxena static void mpi3mr_flush_io(struct mpi3mr_softc *sc);
852d1d418eSSumit Saxena static int mpi3mr_issue_reset(struct mpi3mr_softc *sc, U16 reset_type,
863012fa8fSChandrakanth patil 	U16 reset_reason);
872d1d418eSSumit Saxena static void mpi3mr_dev_rmhs_send_tm(struct mpi3mr_softc *sc, U16 handle,
882d1d418eSSumit Saxena 	struct mpi3mr_drvr_cmd *cmdparam, U8 iou_rc);
892d1d418eSSumit Saxena static void mpi3mr_dev_rmhs_complete_iou(struct mpi3mr_softc *sc,
902d1d418eSSumit Saxena 	struct mpi3mr_drvr_cmd *drv_cmd);
912d1d418eSSumit Saxena static void mpi3mr_dev_rmhs_complete_tm(struct mpi3mr_softc *sc,
922d1d418eSSumit Saxena 	struct mpi3mr_drvr_cmd *drv_cmd);
932d1d418eSSumit Saxena static void mpi3mr_send_evt_ack(struct mpi3mr_softc *sc, U8 event,
942d1d418eSSumit Saxena 	struct mpi3mr_drvr_cmd *cmdparam, U32 event_ctx);
952d1d418eSSumit Saxena static void mpi3mr_print_fault_info(struct mpi3mr_softc *sc);
962d1d418eSSumit Saxena static inline void mpi3mr_set_diagsave(struct mpi3mr_softc *sc);
972d1d418eSSumit Saxena static const char *mpi3mr_reset_rc_name(enum mpi3mr_reset_reason reason_code);
982d1d418eSSumit Saxena 
992d1d418eSSumit Saxena void
mpi3mr_hexdump(void * buf,int sz,int format)1002d1d418eSSumit Saxena mpi3mr_hexdump(void *buf, int sz, int format)
1012d1d418eSSumit Saxena {
1022d1d418eSSumit Saxena         int i;
1032d1d418eSSumit Saxena         U32 *buf_loc = (U32 *)buf;
1042d1d418eSSumit Saxena 
1052d1d418eSSumit Saxena         for (i = 0; i < (sz / sizeof(U32)); i++) {
1062d1d418eSSumit Saxena                 if ((i % format) == 0) {
1072d1d418eSSumit Saxena                         if (i != 0)
1082d1d418eSSumit Saxena                                 printf("\n");
1092d1d418eSSumit Saxena                         printf("%08x: ", (i * 4));
1102d1d418eSSumit Saxena                 }
1112d1d418eSSumit Saxena                 printf("%08x ", buf_loc[i]);
1122d1d418eSSumit Saxena         }
1132d1d418eSSumit Saxena         printf("\n");
1142d1d418eSSumit Saxena }
1152d1d418eSSumit Saxena 
1162d1d418eSSumit Saxena void
init_completion(struct completion * completion)1172d1d418eSSumit Saxena init_completion(struct completion *completion)
1182d1d418eSSumit Saxena {
1192d1d418eSSumit Saxena 	completion->done = 0;
1202d1d418eSSumit Saxena }
1212d1d418eSSumit Saxena 
1222d1d418eSSumit Saxena void
complete(struct completion * completion)1232d1d418eSSumit Saxena complete(struct completion *completion)
1242d1d418eSSumit Saxena {
1252d1d418eSSumit Saxena 	completion->done = 1;
1262d1d418eSSumit Saxena 	wakeup(complete);
1272d1d418eSSumit Saxena }
1282d1d418eSSumit Saxena 
wait_for_completion_timeout(struct completion * completion,U32 timeout)1292d1d418eSSumit Saxena void wait_for_completion_timeout(struct completion *completion,
1302d1d418eSSumit Saxena 	    U32 timeout)
1312d1d418eSSumit Saxena {
1322d1d418eSSumit Saxena 	U32 count = timeout * 1000;
1332d1d418eSSumit Saxena 
1342d1d418eSSumit Saxena 	while ((completion->done == 0) && count) {
1352d1d418eSSumit Saxena                 DELAY(1000);
1362d1d418eSSumit Saxena 		count--;
1372d1d418eSSumit Saxena 	}
1382d1d418eSSumit Saxena 
1392d1d418eSSumit Saxena 	if (completion->done == 0) {
1402d1d418eSSumit Saxena 		printf("%s: Command is timedout\n", __func__);
1412d1d418eSSumit Saxena 		completion->done = 1;
1422d1d418eSSumit Saxena 	}
1432d1d418eSSumit Saxena }
wait_for_completion_timeout_tm(struct completion * completion,U32 timeout,struct mpi3mr_softc * sc)1442d1d418eSSumit Saxena void wait_for_completion_timeout_tm(struct completion *completion,
1452d1d418eSSumit Saxena 	    U32 timeout, struct mpi3mr_softc *sc)
1462d1d418eSSumit Saxena {
1472d1d418eSSumit Saxena 	U32 count = timeout * 1000;
1482d1d418eSSumit Saxena 
1492d1d418eSSumit Saxena 	while ((completion->done == 0) && count) {
1502d1d418eSSumit Saxena 		msleep(&sc->tm_chan, &sc->mpi3mr_mtx, PRIBIO,
1512d1d418eSSumit Saxena 		       "TM command", 1 * hz);
1522d1d418eSSumit Saxena 		count--;
1532d1d418eSSumit Saxena 	}
1542d1d418eSSumit Saxena 
1552d1d418eSSumit Saxena 	if (completion->done == 0) {
1562d1d418eSSumit Saxena 		printf("%s: Command is timedout\n", __func__);
1572d1d418eSSumit Saxena 		completion->done = 1;
1582d1d418eSSumit Saxena 	}
1592d1d418eSSumit Saxena }
1602d1d418eSSumit Saxena 
1612d1d418eSSumit Saxena 
1622d1d418eSSumit Saxena void
poll_for_command_completion(struct mpi3mr_softc * sc,struct mpi3mr_drvr_cmd * cmd,U16 wait)1632d1d418eSSumit Saxena poll_for_command_completion(struct mpi3mr_softc *sc,
1642d1d418eSSumit Saxena        struct mpi3mr_drvr_cmd *cmd, U16 wait)
1652d1d418eSSumit Saxena {
1662d1d418eSSumit Saxena 	int wait_time = wait * 1000;
1672d1d418eSSumit Saxena        while (wait_time) {
1682d1d418eSSumit Saxena                mpi3mr_complete_admin_cmd(sc);
1692d1d418eSSumit Saxena                if (cmd->state & MPI3MR_CMD_COMPLETE)
1702d1d418eSSumit Saxena                        break;
1712d1d418eSSumit Saxena 	       DELAY(1000);
1722d1d418eSSumit Saxena                wait_time--;
1732d1d418eSSumit Saxena        }
1742d1d418eSSumit Saxena }
1752d1d418eSSumit Saxena 
1762d1d418eSSumit Saxena /**
1772d1d418eSSumit Saxena  * mpi3mr_trigger_snapdump - triggers firmware snapdump
1782d1d418eSSumit Saxena  * @sc: Adapter instance reference
1792d1d418eSSumit Saxena  * @reason_code: reason code for the fault.
1802d1d418eSSumit Saxena  *
1812d1d418eSSumit Saxena  * This routine will trigger the snapdump and wait for it to
1822d1d418eSSumit Saxena  * complete or timeout before it returns.
1832d1d418eSSumit Saxena  * This will be called during initilaization time faults/resets/timeouts
1842d1d418eSSumit Saxena  * before soft reset invocation.
1852d1d418eSSumit Saxena  *
1862d1d418eSSumit Saxena  * Return:  None.
1872d1d418eSSumit Saxena  */
1882d1d418eSSumit Saxena static void
mpi3mr_trigger_snapdump(struct mpi3mr_softc * sc,U16 reason_code)1893012fa8fSChandrakanth patil mpi3mr_trigger_snapdump(struct mpi3mr_softc *sc, U16 reason_code)
1902d1d418eSSumit Saxena {
1912d1d418eSSumit Saxena 	U32 host_diagnostic, timeout = MPI3_SYSIF_DIAG_SAVE_TIMEOUT * 10;
1922d1d418eSSumit Saxena 
1932d1d418eSSumit Saxena 	mpi3mr_dprint(sc, MPI3MR_INFO, "snapdump triggered: reason code: %s\n",
1942d1d418eSSumit Saxena 	    mpi3mr_reset_rc_name(reason_code));
1952d1d418eSSumit Saxena 
1962d1d418eSSumit Saxena 	mpi3mr_set_diagsave(sc);
1972d1d418eSSumit Saxena 	mpi3mr_issue_reset(sc, MPI3_SYSIF_HOST_DIAG_RESET_ACTION_DIAG_FAULT,
1982d1d418eSSumit Saxena 			   reason_code);
1992d1d418eSSumit Saxena 
2002d1d418eSSumit Saxena 	do {
2012d1d418eSSumit Saxena 		host_diagnostic = mpi3mr_regread(sc, MPI3_SYSIF_HOST_DIAG_OFFSET);
2022d1d418eSSumit Saxena 		if (!(host_diagnostic & MPI3_SYSIF_HOST_DIAG_SAVE_IN_PROGRESS))
2032d1d418eSSumit Saxena 			break;
2042d1d418eSSumit Saxena                 DELAY(100 * 1000);
2052d1d418eSSumit Saxena 	} while (--timeout);
2062d1d418eSSumit Saxena 
2072d1d418eSSumit Saxena 	return;
2082d1d418eSSumit Saxena }
2092d1d418eSSumit Saxena 
2102d1d418eSSumit Saxena /**
2112d1d418eSSumit Saxena  * mpi3mr_check_rh_fault_ioc - check reset history and fault
2122d1d418eSSumit Saxena  * controller
2132d1d418eSSumit Saxena  * @sc: Adapter instance reference
2142d1d418eSSumit Saxena  * @reason_code, reason code for the fault.
2152d1d418eSSumit Saxena  *
2162d1d418eSSumit Saxena  * This routine will fault the controller with
2172d1d418eSSumit Saxena  * the given reason code if it is not already in the fault or
2182d1d418eSSumit Saxena  * not asynchronosuly reset. This will be used to handle
2192d1d418eSSumit Saxena  * initilaization time faults/resets/timeout as in those cases
2202d1d418eSSumit Saxena  * immediate soft reset invocation is not required.
2212d1d418eSSumit Saxena  *
2222d1d418eSSumit Saxena  * Return:  None.
2232d1d418eSSumit Saxena  */
mpi3mr_check_rh_fault_ioc(struct mpi3mr_softc * sc,U16 reason_code)2243012fa8fSChandrakanth patil static void mpi3mr_check_rh_fault_ioc(struct mpi3mr_softc *sc, U16 reason_code)
2252d1d418eSSumit Saxena {
2262d1d418eSSumit Saxena 	U32 ioc_status;
2272d1d418eSSumit Saxena 
2282d1d418eSSumit Saxena 	if (sc->unrecoverable) {
2292d1d418eSSumit Saxena 		mpi3mr_dprint(sc, MPI3MR_ERROR, "controller is unrecoverable\n");
2302d1d418eSSumit Saxena 		return;
2312d1d418eSSumit Saxena 	}
2322d1d418eSSumit Saxena 
2332d1d418eSSumit Saxena 	ioc_status = mpi3mr_regread(sc, MPI3_SYSIF_IOC_STATUS_OFFSET);
2342d1d418eSSumit Saxena 	if ((ioc_status & MPI3_SYSIF_IOC_STATUS_RESET_HISTORY) ||
2352d1d418eSSumit Saxena 	    (ioc_status & MPI3_SYSIF_IOC_STATUS_FAULT)) {
2362d1d418eSSumit Saxena 		mpi3mr_print_fault_info(sc);
2372d1d418eSSumit Saxena 		return;
2382d1d418eSSumit Saxena 	}
2392d1d418eSSumit Saxena 
2402d1d418eSSumit Saxena 	mpi3mr_trigger_snapdump(sc, reason_code);
2412d1d418eSSumit Saxena 
2422d1d418eSSumit Saxena 	return;
2432d1d418eSSumit Saxena }
2442d1d418eSSumit Saxena 
mpi3mr_get_reply_virt_addr(struct mpi3mr_softc * sc,bus_addr_t phys_addr)2452d1d418eSSumit Saxena static void * mpi3mr_get_reply_virt_addr(struct mpi3mr_softc *sc,
2462d1d418eSSumit Saxena     bus_addr_t phys_addr)
2472d1d418eSSumit Saxena {
2482d1d418eSSumit Saxena 	if (!phys_addr)
2492d1d418eSSumit Saxena 		return NULL;
2502d1d418eSSumit Saxena 	if ((phys_addr < sc->reply_buf_dma_min_address) ||
2512d1d418eSSumit Saxena 	    (phys_addr > sc->reply_buf_dma_max_address))
2522d1d418eSSumit Saxena 		return NULL;
2532d1d418eSSumit Saxena 
2542d1d418eSSumit Saxena 	return sc->reply_buf + (phys_addr - sc->reply_buf_phys);
2552d1d418eSSumit Saxena }
2562d1d418eSSumit Saxena 
mpi3mr_get_sensebuf_virt_addr(struct mpi3mr_softc * sc,bus_addr_t phys_addr)2572d1d418eSSumit Saxena static void * mpi3mr_get_sensebuf_virt_addr(struct mpi3mr_softc *sc,
2582d1d418eSSumit Saxena     bus_addr_t phys_addr)
2592d1d418eSSumit Saxena {
2602d1d418eSSumit Saxena 	if (!phys_addr)
2612d1d418eSSumit Saxena 		return NULL;
2622d1d418eSSumit Saxena 	return sc->sense_buf + (phys_addr - sc->sense_buf_phys);
2632d1d418eSSumit Saxena }
2642d1d418eSSumit Saxena 
mpi3mr_repost_reply_buf(struct mpi3mr_softc * sc,U64 reply_dma)2652d1d418eSSumit Saxena static void mpi3mr_repost_reply_buf(struct mpi3mr_softc *sc,
2662d1d418eSSumit Saxena     U64 reply_dma)
2672d1d418eSSumit Saxena {
2682d1d418eSSumit Saxena 	U32 old_idx = 0;
2692d1d418eSSumit Saxena 
2702d1d418eSSumit Saxena 	mtx_lock_spin(&sc->reply_free_q_lock);
2712d1d418eSSumit Saxena 	old_idx  =  sc->reply_free_q_host_index;
2722d1d418eSSumit Saxena 	sc->reply_free_q_host_index = ((sc->reply_free_q_host_index ==
2732d1d418eSSumit Saxena 	    (sc->reply_free_q_sz - 1)) ? 0 :
2742d1d418eSSumit Saxena 	    (sc->reply_free_q_host_index + 1));
2752d1d418eSSumit Saxena 	sc->reply_free_q[old_idx] = reply_dma;
2762d1d418eSSumit Saxena 	mpi3mr_regwrite(sc, MPI3_SYSIF_REPLY_FREE_HOST_INDEX_OFFSET,
2772d1d418eSSumit Saxena 		sc->reply_free_q_host_index);
2782d1d418eSSumit Saxena 	mtx_unlock_spin(&sc->reply_free_q_lock);
2792d1d418eSSumit Saxena }
2802d1d418eSSumit Saxena 
mpi3mr_repost_sense_buf(struct mpi3mr_softc * sc,U64 sense_buf_phys)2812d1d418eSSumit Saxena static void mpi3mr_repost_sense_buf(struct mpi3mr_softc *sc,
2822d1d418eSSumit Saxena     U64 sense_buf_phys)
2832d1d418eSSumit Saxena {
2842d1d418eSSumit Saxena 	U32 old_idx = 0;
2852d1d418eSSumit Saxena 
2862d1d418eSSumit Saxena 	mtx_lock_spin(&sc->sense_buf_q_lock);
2872d1d418eSSumit Saxena 	old_idx  =  sc->sense_buf_q_host_index;
2882d1d418eSSumit Saxena 	sc->sense_buf_q_host_index = ((sc->sense_buf_q_host_index ==
2892d1d418eSSumit Saxena 	    (sc->sense_buf_q_sz - 1)) ? 0 :
2902d1d418eSSumit Saxena 	    (sc->sense_buf_q_host_index + 1));
2912d1d418eSSumit Saxena 	sc->sense_buf_q[old_idx] = sense_buf_phys;
2922d1d418eSSumit Saxena 	mpi3mr_regwrite(sc, MPI3_SYSIF_SENSE_BUF_FREE_HOST_INDEX_OFFSET,
2932d1d418eSSumit Saxena 		sc->sense_buf_q_host_index);
2942d1d418eSSumit Saxena 	mtx_unlock_spin(&sc->sense_buf_q_lock);
2952d1d418eSSumit Saxena 
2962d1d418eSSumit Saxena }
2972d1d418eSSumit Saxena 
mpi3mr_set_io_divert_for_all_vd_in_tg(struct mpi3mr_softc * sc,struct mpi3mr_throttle_group_info * tg,U8 divert_value)2982d1d418eSSumit Saxena void mpi3mr_set_io_divert_for_all_vd_in_tg(struct mpi3mr_softc *sc,
2992d1d418eSSumit Saxena 	struct mpi3mr_throttle_group_info *tg, U8 divert_value)
3002d1d418eSSumit Saxena {
3012d1d418eSSumit Saxena 	struct mpi3mr_target *target;
3022d1d418eSSumit Saxena 
3032d1d418eSSumit Saxena 	mtx_lock_spin(&sc->target_lock);
3042d1d418eSSumit Saxena 	TAILQ_FOREACH(target, &sc->cam_sc->tgt_list, tgt_next) {
3052d1d418eSSumit Saxena 		if (target->throttle_group == tg)
3062d1d418eSSumit Saxena 			target->io_divert = divert_value;
3072d1d418eSSumit Saxena 	}
3082d1d418eSSumit Saxena 	mtx_unlock_spin(&sc->target_lock);
3092d1d418eSSumit Saxena }
3102d1d418eSSumit Saxena 
3112d1d418eSSumit Saxena /**
3122d1d418eSSumit Saxena  * mpi3mr_submit_admin_cmd - Submit request to admin queue
3132d1d418eSSumit Saxena  * @mrioc: Adapter reference
3142d1d418eSSumit Saxena  * @admin_req: MPI3 request
3152d1d418eSSumit Saxena  * @admin_req_sz: Request size
3162d1d418eSSumit Saxena  *
3172d1d418eSSumit Saxena  * Post the MPI3 request into admin request queue and
3182d1d418eSSumit Saxena  * inform the controller, if the queue is full return
3192d1d418eSSumit Saxena  * appropriate error.
3202d1d418eSSumit Saxena  *
3212d1d418eSSumit Saxena  * Return: 0 on success, non-zero on failure.
3222d1d418eSSumit Saxena  */
mpi3mr_submit_admin_cmd(struct mpi3mr_softc * sc,void * admin_req,U16 admin_req_sz)3232d1d418eSSumit Saxena int mpi3mr_submit_admin_cmd(struct mpi3mr_softc *sc, void *admin_req,
3242d1d418eSSumit Saxena     U16 admin_req_sz)
3252d1d418eSSumit Saxena {
3262d1d418eSSumit Saxena 	U16 areq_pi = 0, areq_ci = 0, max_entries = 0;
3272d1d418eSSumit Saxena 	int retval = 0;
3282d1d418eSSumit Saxena 	U8 *areq_entry;
3292d1d418eSSumit Saxena 
3302d1d418eSSumit Saxena 	mtx_lock_spin(&sc->admin_req_lock);
3312d1d418eSSumit Saxena 	areq_pi = sc->admin_req_pi;
3322d1d418eSSumit Saxena 	areq_ci = sc->admin_req_ci;
3332d1d418eSSumit Saxena 	max_entries = sc->num_admin_reqs;
3342d1d418eSSumit Saxena 
3352d1d418eSSumit Saxena 	if (sc->unrecoverable)
3362d1d418eSSumit Saxena 		return -EFAULT;
3372d1d418eSSumit Saxena 
3382d1d418eSSumit Saxena 	if ((areq_ci == (areq_pi + 1)) || ((!areq_ci) &&
3392d1d418eSSumit Saxena 					   (areq_pi == (max_entries - 1)))) {
3402d1d418eSSumit Saxena 		printf(IOCNAME "AdminReqQ full condition detected\n",
3412d1d418eSSumit Saxena 		    sc->name);
3422d1d418eSSumit Saxena 		retval = -EAGAIN;
3432d1d418eSSumit Saxena 		goto out;
3442d1d418eSSumit Saxena 	}
3452d1d418eSSumit Saxena 	areq_entry = (U8 *)sc->admin_req + (areq_pi *
3462d1d418eSSumit Saxena 						     MPI3MR_AREQ_FRAME_SZ);
3472d1d418eSSumit Saxena 	memset(areq_entry, 0, MPI3MR_AREQ_FRAME_SZ);
3482d1d418eSSumit Saxena 	memcpy(areq_entry, (U8 *)admin_req, admin_req_sz);
3492d1d418eSSumit Saxena 
3502d1d418eSSumit Saxena 	if (++areq_pi == max_entries)
3512d1d418eSSumit Saxena 		areq_pi = 0;
3522d1d418eSSumit Saxena 	sc->admin_req_pi = areq_pi;
3532d1d418eSSumit Saxena 
3542d1d418eSSumit Saxena 	mpi3mr_regwrite(sc, MPI3_SYSIF_ADMIN_REQ_Q_PI_OFFSET, sc->admin_req_pi);
3552d1d418eSSumit Saxena 
3562d1d418eSSumit Saxena out:
3572d1d418eSSumit Saxena 	mtx_unlock_spin(&sc->admin_req_lock);
3582d1d418eSSumit Saxena 	return retval;
3592d1d418eSSumit Saxena }
3602d1d418eSSumit Saxena 
3612d1d418eSSumit Saxena /**
3622d1d418eSSumit Saxena  * mpi3mr_check_req_qfull - Check request queue is full or not
3632d1d418eSSumit Saxena  * @op_req_q: Operational reply queue info
3642d1d418eSSumit Saxena  *
3652d1d418eSSumit Saxena  * Return: true when queue full, false otherwise.
3662d1d418eSSumit Saxena  */
3672d1d418eSSumit Saxena static inline bool
mpi3mr_check_req_qfull(struct mpi3mr_op_req_queue * op_req_q)3682d1d418eSSumit Saxena mpi3mr_check_req_qfull(struct mpi3mr_op_req_queue *op_req_q)
3692d1d418eSSumit Saxena {
3702d1d418eSSumit Saxena 	U16 pi, ci, max_entries;
3712d1d418eSSumit Saxena 	bool is_qfull = false;
3722d1d418eSSumit Saxena 
3732d1d418eSSumit Saxena 	pi = op_req_q->pi;
3742d1d418eSSumit Saxena 	ci = op_req_q->ci;
3752d1d418eSSumit Saxena 	max_entries = op_req_q->num_reqs;
3762d1d418eSSumit Saxena 
3772d1d418eSSumit Saxena 	if ((ci == (pi + 1)) || ((!ci) && (pi == (max_entries - 1))))
3782d1d418eSSumit Saxena 		is_qfull = true;
3792d1d418eSSumit Saxena 
3802d1d418eSSumit Saxena 	return is_qfull;
3812d1d418eSSumit Saxena }
3822d1d418eSSumit Saxena 
3832d1d418eSSumit Saxena /**
3842d1d418eSSumit Saxena  * mpi3mr_submit_io - Post IO command to firmware
3852d1d418eSSumit Saxena  * @sc:		      Adapter instance reference
3862d1d418eSSumit Saxena  * @op_req_q:	      Operational Request queue reference
3872d1d418eSSumit Saxena  * @req:	      MPT request data
3882d1d418eSSumit Saxena  *
3892d1d418eSSumit Saxena  * This function submits IO command to firmware.
3902d1d418eSSumit Saxena  *
3912d1d418eSSumit Saxena  * Return: Nothing
3922d1d418eSSumit Saxena  */
mpi3mr_submit_io(struct mpi3mr_softc * sc,struct mpi3mr_op_req_queue * op_req_q,U8 * req)3932d1d418eSSumit Saxena int mpi3mr_submit_io(struct mpi3mr_softc *sc,
3942d1d418eSSumit Saxena     struct mpi3mr_op_req_queue *op_req_q, U8 *req)
3952d1d418eSSumit Saxena {
3962d1d418eSSumit Saxena 	U16 pi, max_entries;
3972d1d418eSSumit Saxena 	int retval = 0;
3982d1d418eSSumit Saxena 	U8 *req_entry;
3992d1d418eSSumit Saxena 	U16 req_sz = sc->facts.op_req_sz;
4002d1d418eSSumit Saxena 	struct mpi3mr_irq_context *irq_ctx;
4012d1d418eSSumit Saxena 
4022d1d418eSSumit Saxena 	mtx_lock_spin(&op_req_q->q_lock);
4032d1d418eSSumit Saxena 
4042d1d418eSSumit Saxena 	pi = op_req_q->pi;
4052d1d418eSSumit Saxena 	max_entries = op_req_q->num_reqs;
4062d1d418eSSumit Saxena 	if (mpi3mr_check_req_qfull(op_req_q)) {
4072d1d418eSSumit Saxena 		irq_ctx = &sc->irq_ctx[op_req_q->reply_qid - 1];
4082d1d418eSSumit Saxena 		mpi3mr_complete_io_cmd(sc, irq_ctx);
4092d1d418eSSumit Saxena 
4102d1d418eSSumit Saxena 		if (mpi3mr_check_req_qfull(op_req_q)) {
4112d1d418eSSumit Saxena 			printf(IOCNAME "OpReqQ full condition detected\n",
4122d1d418eSSumit Saxena 				sc->name);
4132d1d418eSSumit Saxena 			retval = -EBUSY;
4142d1d418eSSumit Saxena 			goto out;
4152d1d418eSSumit Saxena 		}
4162d1d418eSSumit Saxena 	}
4172d1d418eSSumit Saxena 
4182d1d418eSSumit Saxena 	req_entry = (U8 *)op_req_q->q_base + (pi * req_sz);
4192d1d418eSSumit Saxena 	memset(req_entry, 0, req_sz);
4202d1d418eSSumit Saxena 	memcpy(req_entry, req, MPI3MR_AREQ_FRAME_SZ);
4212d1d418eSSumit Saxena 	if (++pi == max_entries)
4222d1d418eSSumit Saxena 		pi = 0;
4232d1d418eSSumit Saxena 	op_req_q->pi = pi;
4242d1d418eSSumit Saxena 
4252d1d418eSSumit Saxena 	mpi3mr_atomic_inc(&sc->op_reply_q[op_req_q->reply_qid - 1].pend_ios);
4262d1d418eSSumit Saxena 
4272d1d418eSSumit Saxena 	mpi3mr_regwrite(sc, MPI3_SYSIF_OPER_REQ_Q_N_PI_OFFSET(op_req_q->qid), op_req_q->pi);
4282d1d418eSSumit Saxena 	if (sc->mpi3mr_debug & MPI3MR_TRACE) {
4292d1d418eSSumit Saxena 		device_printf(sc->mpi3mr_dev, "IO submission: QID:%d PI:0x%x\n", op_req_q->qid, op_req_q->pi);
4302d1d418eSSumit Saxena 		mpi3mr_hexdump(req_entry, MPI3MR_AREQ_FRAME_SZ, 8);
4312d1d418eSSumit Saxena 	}
4322d1d418eSSumit Saxena 
4332d1d418eSSumit Saxena out:
4342d1d418eSSumit Saxena 	mtx_unlock_spin(&op_req_q->q_lock);
4352d1d418eSSumit Saxena 	return retval;
4362d1d418eSSumit Saxena }
4372d1d418eSSumit Saxena 
4382d1d418eSSumit Saxena inline void
mpi3mr_add_sg_single(void * paddr,U8 flags,U32 length,bus_addr_t dma_addr)4392d1d418eSSumit Saxena mpi3mr_add_sg_single(void *paddr, U8 flags, U32 length,
4402d1d418eSSumit Saxena 		     bus_addr_t dma_addr)
4412d1d418eSSumit Saxena {
4422d1d418eSSumit Saxena 	Mpi3SGESimple_t *sgel = paddr;
4432d1d418eSSumit Saxena 
4442d1d418eSSumit Saxena 	sgel->Flags = flags;
4452d1d418eSSumit Saxena 	sgel->Length = (length);
4462d1d418eSSumit Saxena 	sgel->Address = (U64)dma_addr;
4472d1d418eSSumit Saxena }
4482d1d418eSSumit Saxena 
mpi3mr_build_zero_len_sge(void * paddr)4492d1d418eSSumit Saxena void mpi3mr_build_zero_len_sge(void *paddr)
4502d1d418eSSumit Saxena {
4512d1d418eSSumit Saxena 	U8 sgl_flags = (MPI3_SGE_FLAGS_ELEMENT_TYPE_SIMPLE |
4522d1d418eSSumit Saxena 		MPI3_SGE_FLAGS_DLAS_SYSTEM | MPI3_SGE_FLAGS_END_OF_LIST);
4532d1d418eSSumit Saxena 
4542d1d418eSSumit Saxena 	mpi3mr_add_sg_single(paddr, sgl_flags, 0, -1);
4552d1d418eSSumit Saxena 
4562d1d418eSSumit Saxena }
4572d1d418eSSumit Saxena 
mpi3mr_enable_interrupts(struct mpi3mr_softc * sc)4582d1d418eSSumit Saxena void mpi3mr_enable_interrupts(struct mpi3mr_softc *sc)
4592d1d418eSSumit Saxena {
4602d1d418eSSumit Saxena 	sc->intr_enabled = 1;
4612d1d418eSSumit Saxena }
4622d1d418eSSumit Saxena 
mpi3mr_disable_interrupts(struct mpi3mr_softc * sc)4632d1d418eSSumit Saxena void mpi3mr_disable_interrupts(struct mpi3mr_softc *sc)
4642d1d418eSSumit Saxena {
4652d1d418eSSumit Saxena 	sc->intr_enabled = 0;
4662d1d418eSSumit Saxena }
4672d1d418eSSumit Saxena 
4682d1d418eSSumit Saxena void
mpi3mr_memaddr_cb(void * arg,bus_dma_segment_t * segs,int nsegs,int error)4692d1d418eSSumit Saxena mpi3mr_memaddr_cb(void *arg, bus_dma_segment_t *segs, int nsegs, int error)
4702d1d418eSSumit Saxena {
4712d1d418eSSumit Saxena 	bus_addr_t *addr;
4722d1d418eSSumit Saxena 
4732d1d418eSSumit Saxena 	addr = arg;
4742d1d418eSSumit Saxena 	*addr = segs[0].ds_addr;
4752d1d418eSSumit Saxena }
4762d1d418eSSumit Saxena 
mpi3mr_delete_op_reply_queue(struct mpi3mr_softc * sc,U16 qid)4772d1d418eSSumit Saxena static int mpi3mr_delete_op_reply_queue(struct mpi3mr_softc *sc, U16 qid)
4782d1d418eSSumit Saxena {
4792d1d418eSSumit Saxena 	Mpi3DeleteReplyQueueRequest_t delq_req;
4802d1d418eSSumit Saxena 	struct mpi3mr_op_reply_queue *op_reply_q;
4812d1d418eSSumit Saxena 	int retval = 0;
4822d1d418eSSumit Saxena 
4832d1d418eSSumit Saxena 
4842d1d418eSSumit Saxena 	op_reply_q = &sc->op_reply_q[qid - 1];
4852d1d418eSSumit Saxena 
4862d1d418eSSumit Saxena 	if (!op_reply_q->qid)
4872d1d418eSSumit Saxena 	{
4882d1d418eSSumit Saxena 		retval = -1;
4892d1d418eSSumit Saxena 		printf(IOCNAME "Issue DelRepQ: called with invalid Reply QID\n",
4902d1d418eSSumit Saxena 		    sc->name);
4912d1d418eSSumit Saxena 		goto out;
4922d1d418eSSumit Saxena 	}
4932d1d418eSSumit Saxena 
4942d1d418eSSumit Saxena 	memset(&delq_req, 0, sizeof(delq_req));
4952d1d418eSSumit Saxena 
4962d1d418eSSumit Saxena 	mtx_lock(&sc->init_cmds.completion.lock);
4972d1d418eSSumit Saxena 	if (sc->init_cmds.state & MPI3MR_CMD_PENDING) {
4982d1d418eSSumit Saxena 		retval = -1;
4992d1d418eSSumit Saxena 		printf(IOCNAME "Issue DelRepQ: Init command is in use\n",
5002d1d418eSSumit Saxena 		    sc->name);
5012d1d418eSSumit Saxena 		mtx_unlock(&sc->init_cmds.completion.lock);
5022d1d418eSSumit Saxena 		goto out;
5032d1d418eSSumit Saxena 	}
5042d1d418eSSumit Saxena 
5052d1d418eSSumit Saxena 	if (sc->init_cmds.state & MPI3MR_CMD_PENDING) {
5062d1d418eSSumit Saxena 		retval = -1;
5072d1d418eSSumit Saxena 		printf(IOCNAME "Issue DelRepQ: Init command is in use\n",
5082d1d418eSSumit Saxena 		    sc->name);
5092d1d418eSSumit Saxena 		goto out;
5102d1d418eSSumit Saxena 	}
5112d1d418eSSumit Saxena 	sc->init_cmds.state = MPI3MR_CMD_PENDING;
5122d1d418eSSumit Saxena 	sc->init_cmds.is_waiting = 1;
5132d1d418eSSumit Saxena 	sc->init_cmds.callback = NULL;
5142d1d418eSSumit Saxena 	delq_req.HostTag = MPI3MR_HOSTTAG_INITCMDS;
5152d1d418eSSumit Saxena 	delq_req.Function = MPI3_FUNCTION_DELETE_REPLY_QUEUE;
5162d1d418eSSumit Saxena 	delq_req.QueueID = qid;
5172d1d418eSSumit Saxena 
5182d1d418eSSumit Saxena 	init_completion(&sc->init_cmds.completion);
5192d1d418eSSumit Saxena 	retval = mpi3mr_submit_admin_cmd(sc, &delq_req, sizeof(delq_req));
5202d1d418eSSumit Saxena 	if (retval) {
5212d1d418eSSumit Saxena 		printf(IOCNAME "Issue DelRepQ: Admin Post failed\n",
5222d1d418eSSumit Saxena 		    sc->name);
5232d1d418eSSumit Saxena 		goto out_unlock;
5242d1d418eSSumit Saxena 	}
5252d1d418eSSumit Saxena 	wait_for_completion_timeout(&sc->init_cmds.completion,
5262d1d418eSSumit Saxena 	    (MPI3MR_INTADMCMD_TIMEOUT));
5272d1d418eSSumit Saxena 	if (!(sc->init_cmds.state & MPI3MR_CMD_COMPLETE)) {
5282d1d418eSSumit Saxena 		printf(IOCNAME "Issue DelRepQ: command timed out\n",
5292d1d418eSSumit Saxena 		    sc->name);
5302d1d418eSSumit Saxena 		mpi3mr_check_rh_fault_ioc(sc,
5312d1d418eSSumit Saxena 		    MPI3MR_RESET_FROM_DELREPQ_TIMEOUT);
5322d1d418eSSumit Saxena 		sc->unrecoverable = 1;
5332d1d418eSSumit Saxena 
5342d1d418eSSumit Saxena 		retval = -1;
5352d1d418eSSumit Saxena 		goto out_unlock;
5362d1d418eSSumit Saxena 	}
5372d1d418eSSumit Saxena 	if ((sc->init_cmds.ioc_status & MPI3_IOCSTATUS_STATUS_MASK)
5382d1d418eSSumit Saxena 	     != MPI3_IOCSTATUS_SUCCESS ) {
5392d1d418eSSumit Saxena 		printf(IOCNAME "Issue DelRepQ: Failed IOCStatus(0x%04x) "
5402d1d418eSSumit Saxena 		    " Loginfo(0x%08x) \n" , sc->name,
5412d1d418eSSumit Saxena 		    (sc->init_cmds.ioc_status & MPI3_IOCSTATUS_STATUS_MASK),
5422d1d418eSSumit Saxena 		    sc->init_cmds.ioc_loginfo);
5432d1d418eSSumit Saxena 		retval = -1;
5442d1d418eSSumit Saxena 		goto out_unlock;
5452d1d418eSSumit Saxena 	}
5462d1d418eSSumit Saxena 	sc->irq_ctx[qid - 1].op_reply_q = NULL;
5472d1d418eSSumit Saxena 
5482d1d418eSSumit Saxena 	if (sc->op_reply_q[qid - 1].q_base_phys != 0)
5492d1d418eSSumit Saxena 		bus_dmamap_unload(sc->op_reply_q[qid - 1].q_base_tag, sc->op_reply_q[qid - 1].q_base_dmamap);
5502d1d418eSSumit Saxena 	if (sc->op_reply_q[qid - 1].q_base != NULL)
5512d1d418eSSumit Saxena 		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);
5522d1d418eSSumit Saxena 	if (sc->op_reply_q[qid - 1].q_base_tag != NULL)
5532d1d418eSSumit Saxena 		bus_dma_tag_destroy(sc->op_reply_q[qid - 1].q_base_tag);
5542d1d418eSSumit Saxena 
5552d1d418eSSumit Saxena 	sc->op_reply_q[qid - 1].q_base = NULL;
5562d1d418eSSumit Saxena 	sc->op_reply_q[qid - 1].qid = 0;
5572d1d418eSSumit Saxena out_unlock:
5582d1d418eSSumit Saxena 	sc->init_cmds.state = MPI3MR_CMD_NOTUSED;
5592d1d418eSSumit Saxena 	mtx_unlock(&sc->init_cmds.completion.lock);
5602d1d418eSSumit Saxena out:
5612d1d418eSSumit Saxena 	return retval;
5622d1d418eSSumit Saxena }
5632d1d418eSSumit Saxena 
5642d1d418eSSumit Saxena /**
5652d1d418eSSumit Saxena  * mpi3mr_create_op_reply_queue - create operational reply queue
5662d1d418eSSumit Saxena  * @sc: Adapter instance reference
5672d1d418eSSumit Saxena  * @qid: operational reply queue id
5682d1d418eSSumit Saxena  *
5692d1d418eSSumit Saxena  * Create operatinal reply queue by issuing MPI request
5702d1d418eSSumit Saxena  * through admin queue.
5712d1d418eSSumit Saxena  *
5722d1d418eSSumit Saxena  * Return:  0 on success, non-zero on failure.
5732d1d418eSSumit Saxena  */
mpi3mr_create_op_reply_queue(struct mpi3mr_softc * sc,U16 qid)5742d1d418eSSumit Saxena static int mpi3mr_create_op_reply_queue(struct mpi3mr_softc *sc, U16 qid)
5752d1d418eSSumit Saxena {
5762d1d418eSSumit Saxena 	Mpi3CreateReplyQueueRequest_t create_req;
5772d1d418eSSumit Saxena 	struct mpi3mr_op_reply_queue *op_reply_q;
5782d1d418eSSumit Saxena 	int retval = 0;
5792d1d418eSSumit Saxena 	char q_lock_name[32];
5802d1d418eSSumit Saxena 
5812d1d418eSSumit Saxena 	op_reply_q = &sc->op_reply_q[qid - 1];
5822d1d418eSSumit Saxena 
5832d1d418eSSumit Saxena 	if (op_reply_q->qid)
5842d1d418eSSumit Saxena 	{
5852d1d418eSSumit Saxena 		retval = -1;
5862d1d418eSSumit Saxena 		printf(IOCNAME "CreateRepQ: called for duplicate qid %d\n",
5872d1d418eSSumit Saxena 		    sc->name, op_reply_q->qid);
5882d1d418eSSumit Saxena 		return retval;
5892d1d418eSSumit Saxena 	}
5902d1d418eSSumit Saxena 
5912d1d418eSSumit Saxena 	op_reply_q->ci = 0;
5922d1d418eSSumit Saxena 	if (pci_get_revid(sc->mpi3mr_dev) == SAS4116_CHIP_REV_A0)
5932d1d418eSSumit Saxena 		op_reply_q->num_replies = MPI3MR_OP_REP_Q_QD_A0;
5942d1d418eSSumit Saxena 	else
5952d1d418eSSumit Saxena 		op_reply_q->num_replies = MPI3MR_OP_REP_Q_QD;
5962d1d418eSSumit Saxena 
5972d1d418eSSumit Saxena 	op_reply_q->qsz = op_reply_q->num_replies * sc->op_reply_sz;
5982d1d418eSSumit Saxena 	op_reply_q->ephase = 1;
5992d1d418eSSumit Saxena 
6002d1d418eSSumit Saxena         if (!op_reply_q->q_base) {
6012d1d418eSSumit Saxena 		snprintf(q_lock_name, 32, "Reply Queue Lock[%d]", qid);
6022d1d418eSSumit Saxena 		mtx_init(&op_reply_q->q_lock, q_lock_name, NULL, MTX_SPIN);
6032d1d418eSSumit Saxena 
6042d1d418eSSumit Saxena 		if (bus_dma_tag_create(sc->mpi3mr_parent_dmat,    /* parent */
6052d1d418eSSumit Saxena 					4, 0,			/* algnmnt, boundary */
606ee7c431cSWarner Losh 					sc->dma_loaddr,		/* lowaddr */
6071ec7c672SWarner Losh 					BUS_SPACE_MAXADDR,	/* highaddr */
6082d1d418eSSumit Saxena 					NULL, NULL,		/* filter, filterarg */
6092d1d418eSSumit Saxena 					op_reply_q->qsz,		/* maxsize */
6102d1d418eSSumit Saxena 					1,			/* nsegments */
6112d1d418eSSumit Saxena 					op_reply_q->qsz,		/* maxsegsize */
6122d1d418eSSumit Saxena 					0,			/* flags */
6132d1d418eSSumit Saxena 					NULL, NULL,		/* lockfunc, lockarg */
6142d1d418eSSumit Saxena 					&op_reply_q->q_base_tag)) {
6152d1d418eSSumit Saxena 			mpi3mr_dprint(sc, MPI3MR_ERROR, "Cannot allocate Operational reply DMA tag\n");
6162d1d418eSSumit Saxena 			return (ENOMEM);
6172d1d418eSSumit Saxena 		}
6182d1d418eSSumit Saxena 
6192d1d418eSSumit Saxena 		if (bus_dmamem_alloc(op_reply_q->q_base_tag, (void **)&op_reply_q->q_base,
6202d1d418eSSumit Saxena 		    BUS_DMA_NOWAIT, &op_reply_q->q_base_dmamap)) {
621ee7c431cSWarner Losh 			mpi3mr_dprint(sc, MPI3MR_ERROR, "%s: Cannot allocate replies memory\n", __func__);
6222d1d418eSSumit Saxena 			return (ENOMEM);
6232d1d418eSSumit Saxena 		}
6242d1d418eSSumit Saxena 		bzero(op_reply_q->q_base, op_reply_q->qsz);
6252d1d418eSSumit Saxena 		bus_dmamap_load(op_reply_q->q_base_tag, op_reply_q->q_base_dmamap, op_reply_q->q_base, op_reply_q->qsz,
62639a3e6a8SAlexander Motin 		    mpi3mr_memaddr_cb, &op_reply_q->q_base_phys, BUS_DMA_NOWAIT);
6272d1d418eSSumit Saxena 		mpi3mr_dprint(sc, MPI3MR_XINFO, "Operational Reply queue ID: %d phys addr= %#016jx virt_addr: %pa size= %d\n",
6282d1d418eSSumit Saxena 		    qid, (uintmax_t)op_reply_q->q_base_phys, op_reply_q->q_base, op_reply_q->qsz);
6292d1d418eSSumit Saxena 
6302d1d418eSSumit Saxena 		if (!op_reply_q->q_base)
6312d1d418eSSumit Saxena 		{
6322d1d418eSSumit Saxena 			retval = -1;
6332d1d418eSSumit Saxena 			printf(IOCNAME "CreateRepQ: memory alloc failed for qid %d\n",
6342d1d418eSSumit Saxena 			    sc->name, qid);
6352d1d418eSSumit Saxena 			goto out;
6362d1d418eSSumit Saxena 		}
6372d1d418eSSumit Saxena 	}
6382d1d418eSSumit Saxena 
6392d1d418eSSumit Saxena 	memset(&create_req, 0, sizeof(create_req));
6402d1d418eSSumit Saxena 
6412d1d418eSSumit Saxena 	mtx_lock(&sc->init_cmds.completion.lock);
6422d1d418eSSumit Saxena 	if (sc->init_cmds.state & MPI3MR_CMD_PENDING) {
6432d1d418eSSumit Saxena 		retval = -1;
6442d1d418eSSumit Saxena 		printf(IOCNAME "CreateRepQ: Init command is in use\n",
6452d1d418eSSumit Saxena 		    sc->name);
6462d1d418eSSumit Saxena 		mtx_unlock(&sc->init_cmds.completion.lock);
6472d1d418eSSumit Saxena 		goto out;
6482d1d418eSSumit Saxena 	}
6492d1d418eSSumit Saxena 
6502d1d418eSSumit Saxena 	sc->init_cmds.state = MPI3MR_CMD_PENDING;
6512d1d418eSSumit Saxena 	sc->init_cmds.is_waiting = 1;
6522d1d418eSSumit Saxena 	sc->init_cmds.callback = NULL;
6532d1d418eSSumit Saxena 	create_req.HostTag = MPI3MR_HOSTTAG_INITCMDS;
6542d1d418eSSumit Saxena 	create_req.Function = MPI3_FUNCTION_CREATE_REPLY_QUEUE;
6552d1d418eSSumit Saxena 	create_req.QueueID = qid;
6562d1d418eSSumit Saxena 	create_req.Flags = MPI3_CREATE_REPLY_QUEUE_FLAGS_INT_ENABLE_ENABLE;
6572d1d418eSSumit Saxena 	create_req.MSIxIndex = sc->irq_ctx[qid - 1].msix_index;
6582d1d418eSSumit Saxena 	create_req.BaseAddress = (U64)op_reply_q->q_base_phys;
6592d1d418eSSumit Saxena 	create_req.Size = op_reply_q->num_replies;
6602d1d418eSSumit Saxena 
6612d1d418eSSumit Saxena 	init_completion(&sc->init_cmds.completion);
6622d1d418eSSumit Saxena 	retval = mpi3mr_submit_admin_cmd(sc, &create_req,
6632d1d418eSSumit Saxena 	    sizeof(create_req));
6642d1d418eSSumit Saxena 	if (retval) {
6652d1d418eSSumit Saxena 		printf(IOCNAME "CreateRepQ: Admin Post failed\n",
6662d1d418eSSumit Saxena 		    sc->name);
6672d1d418eSSumit Saxena 		goto out_unlock;
6682d1d418eSSumit Saxena 	}
6692d1d418eSSumit Saxena 
6702d1d418eSSumit Saxena 	wait_for_completion_timeout(&sc->init_cmds.completion,
6712d1d418eSSumit Saxena 	  	MPI3MR_INTADMCMD_TIMEOUT);
6722d1d418eSSumit Saxena 	if (!(sc->init_cmds.state & MPI3MR_CMD_COMPLETE)) {
6732d1d418eSSumit Saxena 		printf(IOCNAME "CreateRepQ: command timed out\n",
6742d1d418eSSumit Saxena 		    sc->name);
6752d1d418eSSumit Saxena 		mpi3mr_check_rh_fault_ioc(sc,
6762d1d418eSSumit Saxena 		    MPI3MR_RESET_FROM_CREATEREPQ_TIMEOUT);
6772d1d418eSSumit Saxena 		sc->unrecoverable = 1;
6782d1d418eSSumit Saxena 		retval = -1;
6792d1d418eSSumit Saxena 		goto out_unlock;
6802d1d418eSSumit Saxena 	}
6812d1d418eSSumit Saxena 
6822d1d418eSSumit Saxena 	if ((sc->init_cmds.ioc_status & MPI3_IOCSTATUS_STATUS_MASK)
6832d1d418eSSumit Saxena 	     != MPI3_IOCSTATUS_SUCCESS ) {
6842d1d418eSSumit Saxena 		printf(IOCNAME "CreateRepQ: Failed IOCStatus(0x%04x) "
6852d1d418eSSumit Saxena 		    " Loginfo(0x%08x) \n" , sc->name,
6862d1d418eSSumit Saxena 		    (sc->init_cmds.ioc_status & MPI3_IOCSTATUS_STATUS_MASK),
6872d1d418eSSumit Saxena 		    sc->init_cmds.ioc_loginfo);
6882d1d418eSSumit Saxena 		retval = -1;
6892d1d418eSSumit Saxena 		goto out_unlock;
6902d1d418eSSumit Saxena 	}
6912d1d418eSSumit Saxena 	op_reply_q->qid = qid;
6922d1d418eSSumit Saxena 	sc->irq_ctx[qid - 1].op_reply_q = op_reply_q;
6932d1d418eSSumit Saxena 
6942d1d418eSSumit Saxena out_unlock:
6952d1d418eSSumit Saxena 	sc->init_cmds.state = MPI3MR_CMD_NOTUSED;
6962d1d418eSSumit Saxena 	mtx_unlock(&sc->init_cmds.completion.lock);
6972d1d418eSSumit Saxena out:
6982d1d418eSSumit Saxena 	if (retval) {
6992d1d418eSSumit Saxena 		if (op_reply_q->q_base_phys != 0)
7002d1d418eSSumit Saxena 			bus_dmamap_unload(op_reply_q->q_base_tag, op_reply_q->q_base_dmamap);
7012d1d418eSSumit Saxena 		if (op_reply_q->q_base != NULL)
7022d1d418eSSumit Saxena 			bus_dmamem_free(op_reply_q->q_base_tag, op_reply_q->q_base, op_reply_q->q_base_dmamap);
7032d1d418eSSumit Saxena 		if (op_reply_q->q_base_tag != NULL)
7042d1d418eSSumit Saxena 			bus_dma_tag_destroy(op_reply_q->q_base_tag);
7052d1d418eSSumit Saxena 		op_reply_q->q_base = NULL;
7062d1d418eSSumit Saxena 		op_reply_q->qid = 0;
7072d1d418eSSumit Saxena 	}
7082d1d418eSSumit Saxena 
7092d1d418eSSumit Saxena 	return retval;
7102d1d418eSSumit Saxena }
7112d1d418eSSumit Saxena 
7122d1d418eSSumit Saxena /**
7132d1d418eSSumit Saxena  * mpi3mr_create_op_req_queue - create operational request queue
7142d1d418eSSumit Saxena  * @sc: Adapter instance reference
7152d1d418eSSumit Saxena  * @req_qid: operational request queue id
7162d1d418eSSumit Saxena  * @reply_qid: Reply queue ID
7172d1d418eSSumit Saxena  *
7182d1d418eSSumit Saxena  * Create operatinal request queue by issuing MPI request
7192d1d418eSSumit Saxena  * through admin queue.
7202d1d418eSSumit Saxena  *
7212d1d418eSSumit Saxena  * Return:  0 on success, non-zero on failure.
7222d1d418eSSumit Saxena  */
mpi3mr_create_op_req_queue(struct mpi3mr_softc * sc,U16 req_qid,U8 reply_qid)7232d1d418eSSumit Saxena static int mpi3mr_create_op_req_queue(struct mpi3mr_softc *sc, U16 req_qid, U8 reply_qid)
7242d1d418eSSumit Saxena {
7252d1d418eSSumit Saxena 	Mpi3CreateRequestQueueRequest_t create_req;
7262d1d418eSSumit Saxena 	struct mpi3mr_op_req_queue *op_req_q;
7272d1d418eSSumit Saxena 	int retval = 0;
7282d1d418eSSumit Saxena 	char q_lock_name[32];
7292d1d418eSSumit Saxena 
7302d1d418eSSumit Saxena 	op_req_q = &sc->op_req_q[req_qid - 1];
7312d1d418eSSumit Saxena 
7322d1d418eSSumit Saxena 	if (op_req_q->qid)
7332d1d418eSSumit Saxena 	{
7342d1d418eSSumit Saxena 		retval = -1;
7352d1d418eSSumit Saxena 		printf(IOCNAME "CreateReqQ: called for duplicate qid %d\n",
7362d1d418eSSumit Saxena 		    sc->name, op_req_q->qid);
7372d1d418eSSumit Saxena 		return retval;
7382d1d418eSSumit Saxena 	}
7392d1d418eSSumit Saxena 
7402d1d418eSSumit Saxena 	op_req_q->ci = 0;
7412d1d418eSSumit Saxena 	op_req_q->pi = 0;
7422d1d418eSSumit Saxena 	op_req_q->num_reqs = MPI3MR_OP_REQ_Q_QD;
7432d1d418eSSumit Saxena 	op_req_q->qsz = op_req_q->num_reqs * sc->facts.op_req_sz;
7442d1d418eSSumit Saxena 	op_req_q->reply_qid = reply_qid;
7452d1d418eSSumit Saxena 
7462d1d418eSSumit Saxena 	if (!op_req_q->q_base) {
7472d1d418eSSumit Saxena 		snprintf(q_lock_name, 32, "Request Queue Lock[%d]", req_qid);
7482d1d418eSSumit Saxena 		mtx_init(&op_req_q->q_lock, q_lock_name, NULL, MTX_SPIN);
7492d1d418eSSumit Saxena 
7502d1d418eSSumit Saxena 		if (bus_dma_tag_create(sc->mpi3mr_parent_dmat,    /* parent */
7512d1d418eSSumit Saxena 					4, 0,			/* algnmnt, boundary */
752ee7c431cSWarner Losh 					sc->dma_loaddr,		/* lowaddr */
7531ec7c672SWarner Losh 					BUS_SPACE_MAXADDR,	/* highaddr */
7542d1d418eSSumit Saxena 					NULL, NULL,		/* filter, filterarg */
7552d1d418eSSumit Saxena 					op_req_q->qsz,		/* maxsize */
7562d1d418eSSumit Saxena 					1,			/* nsegments */
7572d1d418eSSumit Saxena 					op_req_q->qsz,		/* maxsegsize */
7582d1d418eSSumit Saxena 					0,			/* flags */
7592d1d418eSSumit Saxena 					NULL, NULL,		/* lockfunc, lockarg */
7602d1d418eSSumit Saxena 					&op_req_q->q_base_tag)) {
7612d1d418eSSumit Saxena 			mpi3mr_dprint(sc, MPI3MR_ERROR, "Cannot allocate request DMA tag\n");
7622d1d418eSSumit Saxena 			return (ENOMEM);
7632d1d418eSSumit Saxena 		}
7642d1d418eSSumit Saxena 
7652d1d418eSSumit Saxena 		if (bus_dmamem_alloc(op_req_q->q_base_tag, (void **)&op_req_q->q_base,
7662d1d418eSSumit Saxena 		    BUS_DMA_NOWAIT, &op_req_q->q_base_dmamap)) {
767ee7c431cSWarner Losh 			mpi3mr_dprint(sc, MPI3MR_ERROR, "%s: Cannot allocate replies memory\n", __func__);
7682d1d418eSSumit Saxena 			return (ENOMEM);
7692d1d418eSSumit Saxena 		}
7702d1d418eSSumit Saxena 
7712d1d418eSSumit Saxena 		bzero(op_req_q->q_base, op_req_q->qsz);
7722d1d418eSSumit Saxena 
7732d1d418eSSumit Saxena 		bus_dmamap_load(op_req_q->q_base_tag, op_req_q->q_base_dmamap, op_req_q->q_base, op_req_q->qsz,
77439a3e6a8SAlexander Motin 		    mpi3mr_memaddr_cb, &op_req_q->q_base_phys, BUS_DMA_NOWAIT);
7752d1d418eSSumit Saxena 
7762d1d418eSSumit Saxena 		mpi3mr_dprint(sc, MPI3MR_XINFO, "Operational Request QID: %d phys addr= %#016jx virt addr= %pa size= %d associated Reply QID: %d\n",
7772d1d418eSSumit Saxena 		    req_qid, (uintmax_t)op_req_q->q_base_phys, op_req_q->q_base, op_req_q->qsz, reply_qid);
7782d1d418eSSumit Saxena 
7792d1d418eSSumit Saxena 		if (!op_req_q->q_base) {
7802d1d418eSSumit Saxena 			retval = -1;
7812d1d418eSSumit Saxena 			printf(IOCNAME "CreateReqQ: memory alloc failed for qid %d\n",
7822d1d418eSSumit Saxena 			    sc->name, req_qid);
7832d1d418eSSumit Saxena 			goto out;
7842d1d418eSSumit Saxena 		}
7852d1d418eSSumit Saxena 	}
7862d1d418eSSumit Saxena 
7872d1d418eSSumit Saxena 	memset(&create_req, 0, sizeof(create_req));
7882d1d418eSSumit Saxena 
7892d1d418eSSumit Saxena 	mtx_lock(&sc->init_cmds.completion.lock);
7902d1d418eSSumit Saxena 	if (sc->init_cmds.state & MPI3MR_CMD_PENDING) {
7912d1d418eSSumit Saxena 		retval = -1;
7922d1d418eSSumit Saxena 		printf(IOCNAME "CreateReqQ: Init command is in use\n",
7932d1d418eSSumit Saxena 		    sc->name);
7942d1d418eSSumit Saxena 		mtx_unlock(&sc->init_cmds.completion.lock);
7952d1d418eSSumit Saxena 		goto out;
7962d1d418eSSumit Saxena 	}
7972d1d418eSSumit Saxena 
7982d1d418eSSumit Saxena 	sc->init_cmds.state = MPI3MR_CMD_PENDING;
7992d1d418eSSumit Saxena 	sc->init_cmds.is_waiting = 1;
8002d1d418eSSumit Saxena 	sc->init_cmds.callback = NULL;
8012d1d418eSSumit Saxena 	create_req.HostTag = MPI3MR_HOSTTAG_INITCMDS;
8022d1d418eSSumit Saxena 	create_req.Function = MPI3_FUNCTION_CREATE_REQUEST_QUEUE;
8032d1d418eSSumit Saxena 	create_req.QueueID = req_qid;
8042d1d418eSSumit Saxena 	create_req.Flags = 0;
8052d1d418eSSumit Saxena 	create_req.ReplyQueueID = reply_qid;
8062d1d418eSSumit Saxena 	create_req.BaseAddress = (U64)op_req_q->q_base_phys;
8072d1d418eSSumit Saxena 	create_req.Size = op_req_q->num_reqs;
8082d1d418eSSumit Saxena 
8092d1d418eSSumit Saxena 	init_completion(&sc->init_cmds.completion);
8102d1d418eSSumit Saxena 	retval = mpi3mr_submit_admin_cmd(sc, &create_req,
8112d1d418eSSumit Saxena 	    sizeof(create_req));
8122d1d418eSSumit Saxena 	if (retval) {
8132d1d418eSSumit Saxena 		printf(IOCNAME "CreateReqQ: Admin Post failed\n",
8142d1d418eSSumit Saxena 		    sc->name);
8152d1d418eSSumit Saxena 		goto out_unlock;
8162d1d418eSSumit Saxena 	}
8172d1d418eSSumit Saxena 
8182d1d418eSSumit Saxena 	wait_for_completion_timeout(&sc->init_cmds.completion,
8192d1d418eSSumit Saxena 	    (MPI3MR_INTADMCMD_TIMEOUT));
8202d1d418eSSumit Saxena 
8212d1d418eSSumit Saxena 	if (!(sc->init_cmds.state & MPI3MR_CMD_COMPLETE)) {
8222d1d418eSSumit Saxena 		printf(IOCNAME "CreateReqQ: command timed out\n",
8232d1d418eSSumit Saxena 		    sc->name);
8242d1d418eSSumit Saxena 		mpi3mr_check_rh_fault_ioc(sc,
8252d1d418eSSumit Saxena 			MPI3MR_RESET_FROM_CREATEREQQ_TIMEOUT);
8262d1d418eSSumit Saxena 		sc->unrecoverable = 1;
8272d1d418eSSumit Saxena 		retval = -1;
8282d1d418eSSumit Saxena 		goto out_unlock;
8292d1d418eSSumit Saxena 	}
8302d1d418eSSumit Saxena 
8312d1d418eSSumit Saxena 	if ((sc->init_cmds.ioc_status & MPI3_IOCSTATUS_STATUS_MASK)
8322d1d418eSSumit Saxena 	     != MPI3_IOCSTATUS_SUCCESS ) {
8332d1d418eSSumit Saxena 		printf(IOCNAME "CreateReqQ: Failed IOCStatus(0x%04x) "
8342d1d418eSSumit Saxena 		    " Loginfo(0x%08x) \n" , sc->name,
8352d1d418eSSumit Saxena 		    (sc->init_cmds.ioc_status & MPI3_IOCSTATUS_STATUS_MASK),
8362d1d418eSSumit Saxena 		    sc->init_cmds.ioc_loginfo);
8372d1d418eSSumit Saxena 		retval = -1;
8382d1d418eSSumit Saxena 		goto out_unlock;
8392d1d418eSSumit Saxena 	}
8402d1d418eSSumit Saxena 	op_req_q->qid = req_qid;
8412d1d418eSSumit Saxena 
8422d1d418eSSumit Saxena out_unlock:
8432d1d418eSSumit Saxena 	sc->init_cmds.state = MPI3MR_CMD_NOTUSED;
8442d1d418eSSumit Saxena 	mtx_unlock(&sc->init_cmds.completion.lock);
8452d1d418eSSumit Saxena out:
8462d1d418eSSumit Saxena 	if (retval) {
8472d1d418eSSumit Saxena 		if (op_req_q->q_base_phys != 0)
8482d1d418eSSumit Saxena 			bus_dmamap_unload(op_req_q->q_base_tag, op_req_q->q_base_dmamap);
8492d1d418eSSumit Saxena 		if (op_req_q->q_base != NULL)
8502d1d418eSSumit Saxena 			bus_dmamem_free(op_req_q->q_base_tag, op_req_q->q_base, op_req_q->q_base_dmamap);
8512d1d418eSSumit Saxena 		if (op_req_q->q_base_tag != NULL)
8522d1d418eSSumit Saxena 			bus_dma_tag_destroy(op_req_q->q_base_tag);
8532d1d418eSSumit Saxena 		op_req_q->q_base = NULL;
8542d1d418eSSumit Saxena 		op_req_q->qid = 0;
8552d1d418eSSumit Saxena 	}
8562d1d418eSSumit Saxena 	return retval;
8572d1d418eSSumit Saxena }
8582d1d418eSSumit Saxena 
8592d1d418eSSumit Saxena /**
8602d1d418eSSumit Saxena  * mpi3mr_create_op_queues - create operational queues
8612d1d418eSSumit Saxena  * @sc: Adapter instance reference
8622d1d418eSSumit Saxena  *
8632d1d418eSSumit Saxena  * Create operatinal queues(request queues and reply queues).
8642d1d418eSSumit Saxena  * Return:  0 on success, non-zero on failure.
8652d1d418eSSumit Saxena  */
mpi3mr_create_op_queues(struct mpi3mr_softc * sc)8662d1d418eSSumit Saxena static int mpi3mr_create_op_queues(struct mpi3mr_softc *sc)
8672d1d418eSSumit Saxena {
8682d1d418eSSumit Saxena 	int retval = 0;
8692d1d418eSSumit Saxena 	U16 num_queues = 0, i = 0, qid;
8702d1d418eSSumit Saxena 
8712d1d418eSSumit Saxena 	num_queues = min(sc->facts.max_op_reply_q,
8722d1d418eSSumit Saxena 	    sc->facts.max_op_req_q);
8732d1d418eSSumit Saxena 	num_queues = min(num_queues, sc->msix_count);
8742d1d418eSSumit Saxena 
8752d1d418eSSumit Saxena 	/*
8762d1d418eSSumit Saxena 	 * During reset set the num_queues to the number of queues
8772d1d418eSSumit Saxena 	 * that was set before the reset.
8782d1d418eSSumit Saxena 	 */
8792d1d418eSSumit Saxena 	if (sc->num_queues)
8802d1d418eSSumit Saxena 		num_queues = sc->num_queues;
8812d1d418eSSumit Saxena 
8822d1d418eSSumit Saxena 	mpi3mr_dprint(sc, MPI3MR_XINFO, "Trying to create %d Operational Q pairs\n",
8832d1d418eSSumit Saxena 	    num_queues);
8842d1d418eSSumit Saxena 
8852d1d418eSSumit Saxena 	if (!sc->op_req_q) {
8862d1d418eSSumit Saxena 		sc->op_req_q = malloc(sizeof(struct mpi3mr_op_req_queue) *
8872d1d418eSSumit Saxena 		    num_queues, M_MPI3MR, M_NOWAIT | M_ZERO);
8882d1d418eSSumit Saxena 
8892d1d418eSSumit Saxena 		if (!sc->op_req_q) {
8902d1d418eSSumit Saxena 			mpi3mr_dprint(sc, MPI3MR_ERROR, "Failed to alloc memory for Request queue info\n");
8912d1d418eSSumit Saxena 			retval = -1;
8922d1d418eSSumit Saxena 			goto out_failed;
8932d1d418eSSumit Saxena 		}
8942d1d418eSSumit Saxena 	}
8952d1d418eSSumit Saxena 
8962d1d418eSSumit Saxena 	if (!sc->op_reply_q) {
8972d1d418eSSumit Saxena 		sc->op_reply_q = malloc(sizeof(struct mpi3mr_op_reply_queue) * num_queues,
8982d1d418eSSumit Saxena 			M_MPI3MR, M_NOWAIT | M_ZERO);
8992d1d418eSSumit Saxena 
9002d1d418eSSumit Saxena 		if (!sc->op_reply_q) {
9012d1d418eSSumit Saxena 			mpi3mr_dprint(sc, MPI3MR_ERROR, "Failed to alloc memory for Reply queue info\n");
9022d1d418eSSumit Saxena 			retval = -1;
9032d1d418eSSumit Saxena 			goto out_failed;
9042d1d418eSSumit Saxena 		}
9052d1d418eSSumit Saxena 	}
9062d1d418eSSumit Saxena 
9072d1d418eSSumit Saxena 	sc->num_hosttag_op_req_q = (sc->max_host_ios + 1) / num_queues;
9082d1d418eSSumit Saxena 
9092d1d418eSSumit Saxena 	/*Operational Request and reply queue ID starts with 1*/
9102d1d418eSSumit Saxena 	for (i = 0; i < num_queues; i++) {
9112d1d418eSSumit Saxena 		qid = i + 1;
9122d1d418eSSumit Saxena 		if (mpi3mr_create_op_reply_queue(sc, qid)) {
9132d1d418eSSumit Saxena 			mpi3mr_dprint(sc, MPI3MR_ERROR, "Failed to create Reply queue %d\n",
9142d1d418eSSumit Saxena 			    qid);
9152d1d418eSSumit Saxena 			break;
9162d1d418eSSumit Saxena 		}
9172d1d418eSSumit Saxena 		if (mpi3mr_create_op_req_queue(sc, qid,
9182d1d418eSSumit Saxena 		    sc->op_reply_q[qid - 1].qid)) {
9192d1d418eSSumit Saxena 			mpi3mr_delete_op_reply_queue(sc, qid);
9202d1d418eSSumit Saxena 			mpi3mr_dprint(sc, MPI3MR_ERROR, "Failed to create Request queue %d\n",
9212d1d418eSSumit Saxena 			    qid);
9222d1d418eSSumit Saxena 			break;
9232d1d418eSSumit Saxena 		}
9242d1d418eSSumit Saxena 
9252d1d418eSSumit Saxena 	}
9262d1d418eSSumit Saxena 
9272d1d418eSSumit Saxena 	/* Not even one queue is created successfully*/
9282d1d418eSSumit Saxena         if (i == 0) {
9292d1d418eSSumit Saxena                 retval = -1;
9302d1d418eSSumit Saxena                 goto out_failed;
9312d1d418eSSumit Saxena         }
9322d1d418eSSumit Saxena 
9332d1d418eSSumit Saxena 	if (!sc->num_queues) {
9342d1d418eSSumit Saxena 		sc->num_queues = i;
9352d1d418eSSumit Saxena 	} else {
9362d1d418eSSumit Saxena 		if (num_queues != i) {
9372d1d418eSSumit Saxena 			mpi3mr_dprint(sc, MPI3MR_ERROR, "Number of queues (%d) post reset are not same as"
9382d1d418eSSumit Saxena 					"queues allocated (%d) during driver init\n", i, num_queues);
9392d1d418eSSumit Saxena 			goto out_failed;
9402d1d418eSSumit Saxena 		}
9412d1d418eSSumit Saxena 	}
9422d1d418eSSumit Saxena 
9432d1d418eSSumit Saxena 	mpi3mr_dprint(sc, MPI3MR_INFO, "Successfully created %d Operational Queue pairs\n",
9442d1d418eSSumit Saxena 	    sc->num_queues);
9452d1d418eSSumit Saxena 	mpi3mr_dprint(sc, MPI3MR_INFO, "Request Queue QD: %d Reply queue QD: %d\n",
9462d1d418eSSumit Saxena 	    sc->op_req_q[0].num_reqs, sc->op_reply_q[0].num_replies);
9472d1d418eSSumit Saxena 
9482d1d418eSSumit Saxena 	return retval;
9492d1d418eSSumit Saxena out_failed:
9502d1d418eSSumit Saxena 	if (sc->op_req_q) {
9512d1d418eSSumit Saxena 		free(sc->op_req_q, M_MPI3MR);
9522d1d418eSSumit Saxena 		sc->op_req_q = NULL;
9532d1d418eSSumit Saxena 	}
9542d1d418eSSumit Saxena 	if (sc->op_reply_q) {
9552d1d418eSSumit Saxena 		free(sc->op_reply_q, M_MPI3MR);
9562d1d418eSSumit Saxena 		sc->op_reply_q = NULL;
9572d1d418eSSumit Saxena 	}
9582d1d418eSSumit Saxena 	return retval;
9592d1d418eSSumit Saxena }
9602d1d418eSSumit Saxena 
9612d1d418eSSumit Saxena /**
9622d1d418eSSumit Saxena  * mpi3mr_setup_admin_qpair - Setup admin queue pairs
9632d1d418eSSumit Saxena  * @sc: Adapter instance reference
9642d1d418eSSumit Saxena  *
9652d1d418eSSumit Saxena  * Allocation and setup admin queues(request queues and reply queues).
9662d1d418eSSumit Saxena  * Return:  0 on success, non-zero on failure.
9672d1d418eSSumit Saxena  */
mpi3mr_setup_admin_qpair(struct mpi3mr_softc * sc)9682d1d418eSSumit Saxena static int mpi3mr_setup_admin_qpair(struct mpi3mr_softc *sc)
9692d1d418eSSumit Saxena {
9702d1d418eSSumit Saxena 	int retval = 0;
9712d1d418eSSumit Saxena 	U32 num_adm_entries = 0;
9722d1d418eSSumit Saxena 
9732d1d418eSSumit Saxena 	sc->admin_req_q_sz = MPI3MR_AREQQ_SIZE;
9742d1d418eSSumit Saxena 	sc->num_admin_reqs = sc->admin_req_q_sz / MPI3MR_AREQ_FRAME_SZ;
9752d1d418eSSumit Saxena 	sc->admin_req_ci = sc->admin_req_pi = 0;
9762d1d418eSSumit Saxena 
9772d1d418eSSumit Saxena 	sc->admin_reply_q_sz = MPI3MR_AREPQ_SIZE;
9782d1d418eSSumit Saxena 	sc->num_admin_replies = sc->admin_reply_q_sz/ MPI3MR_AREP_FRAME_SZ;
9792d1d418eSSumit Saxena 	sc->admin_reply_ci = 0;
9802d1d418eSSumit Saxena 	sc->admin_reply_ephase = 1;
9812d1d418eSSumit Saxena 
9822d1d418eSSumit Saxena 	if (!sc->admin_req) {
98391d96135SWarner Losh 		/*
98491d96135SWarner Losh 		 * We need to create the tag for the admin queue to get the
98591d96135SWarner Losh 		 * iofacts to see how many bits the controller decodes.  Solve
98691d96135SWarner Losh 		 * this chicken and egg problem by only doing lower 4GB DMA.
98791d96135SWarner Losh 		 */
9882d1d418eSSumit Saxena 		if (bus_dma_tag_create(sc->mpi3mr_parent_dmat,    /* parent */
9892d1d418eSSumit Saxena 					4, 0,			/* algnmnt, boundary */
9902d1d418eSSumit Saxena 					BUS_SPACE_MAXADDR_32BIT,/* lowaddr */
9912d1d418eSSumit Saxena 					BUS_SPACE_MAXADDR,	/* highaddr */
9922d1d418eSSumit Saxena 					NULL, NULL,		/* filter, filterarg */
9932d1d418eSSumit Saxena 					sc->admin_req_q_sz,	/* maxsize */
9942d1d418eSSumit Saxena 					1,			/* nsegments */
9952d1d418eSSumit Saxena 					sc->admin_req_q_sz,	/* maxsegsize */
9962d1d418eSSumit Saxena 					0,			/* flags */
9972d1d418eSSumit Saxena 					NULL, NULL,		/* lockfunc, lockarg */
9982d1d418eSSumit Saxena 					&sc->admin_req_tag)) {
9992d1d418eSSumit Saxena 			mpi3mr_dprint(sc, MPI3MR_ERROR, "Cannot allocate request DMA tag\n");
10002d1d418eSSumit Saxena 			return (ENOMEM);
10012d1d418eSSumit Saxena 		}
10022d1d418eSSumit Saxena 
10032d1d418eSSumit Saxena 		if (bus_dmamem_alloc(sc->admin_req_tag, (void **)&sc->admin_req,
10042d1d418eSSumit Saxena 		    BUS_DMA_NOWAIT, &sc->admin_req_dmamap)) {
1005ee7c431cSWarner Losh 			mpi3mr_dprint(sc, MPI3MR_ERROR, "%s: Cannot allocate replies memory\n", __func__);
10062d1d418eSSumit Saxena 			return (ENOMEM);
10072d1d418eSSumit Saxena 		}
10082d1d418eSSumit Saxena 		bzero(sc->admin_req, sc->admin_req_q_sz);
10092d1d418eSSumit Saxena 		bus_dmamap_load(sc->admin_req_tag, sc->admin_req_dmamap, sc->admin_req, sc->admin_req_q_sz,
101039a3e6a8SAlexander Motin 		    mpi3mr_memaddr_cb, &sc->admin_req_phys, BUS_DMA_NOWAIT);
10112d1d418eSSumit Saxena 		mpi3mr_dprint(sc, MPI3MR_XINFO, "Admin Req queue phys addr= %#016jx size= %d\n",
10122d1d418eSSumit Saxena 		    (uintmax_t)sc->admin_req_phys, sc->admin_req_q_sz);
10132d1d418eSSumit Saxena 
10142d1d418eSSumit Saxena 		if (!sc->admin_req)
10152d1d418eSSumit Saxena 		{
10162d1d418eSSumit Saxena 			retval = -1;
10172d1d418eSSumit Saxena 			printf(IOCNAME "Memory alloc for AdminReqQ: failed\n",
10182d1d418eSSumit Saxena 			    sc->name);
10192d1d418eSSumit Saxena 			goto out_failed;
10202d1d418eSSumit Saxena 		}
10212d1d418eSSumit Saxena 	}
10222d1d418eSSumit Saxena 
10232d1d418eSSumit Saxena 	if (!sc->admin_reply) {
10242d1d418eSSumit Saxena 		mtx_init(&sc->admin_reply_lock, "Admin Reply Queue Lock", NULL, MTX_SPIN);
10252d1d418eSSumit Saxena 
10262d1d418eSSumit Saxena 		if (bus_dma_tag_create(sc->mpi3mr_parent_dmat,    /* parent */
10272d1d418eSSumit Saxena 					4, 0,			/* algnmnt, boundary */
10282d1d418eSSumit Saxena 					BUS_SPACE_MAXADDR_32BIT,/* lowaddr */
10292d1d418eSSumit Saxena 					BUS_SPACE_MAXADDR,	/* highaddr */
10302d1d418eSSumit Saxena 					NULL, NULL,		/* filter, filterarg */
10312d1d418eSSumit Saxena 					sc->admin_reply_q_sz,	/* maxsize */
10322d1d418eSSumit Saxena 					1,			/* nsegments */
10332d1d418eSSumit Saxena 					sc->admin_reply_q_sz,	/* maxsegsize */
10342d1d418eSSumit Saxena 					0,			/* flags */
10352d1d418eSSumit Saxena 					NULL, NULL,		/* lockfunc, lockarg */
10362d1d418eSSumit Saxena 					&sc->admin_reply_tag)) {
10372d1d418eSSumit Saxena 			mpi3mr_dprint(sc, MPI3MR_ERROR, "Cannot allocate reply DMA tag\n");
10382d1d418eSSumit Saxena 			return (ENOMEM);
10392d1d418eSSumit Saxena 		}
10402d1d418eSSumit Saxena 
10412d1d418eSSumit Saxena 		if (bus_dmamem_alloc(sc->admin_reply_tag, (void **)&sc->admin_reply,
10422d1d418eSSumit Saxena 		    BUS_DMA_NOWAIT, &sc->admin_reply_dmamap)) {
1043ee7c431cSWarner Losh 			mpi3mr_dprint(sc, MPI3MR_ERROR, "%s: Cannot allocate replies memory\n", __func__);
10442d1d418eSSumit Saxena 			return (ENOMEM);
10452d1d418eSSumit Saxena 		}
10462d1d418eSSumit Saxena 		bzero(sc->admin_reply, sc->admin_reply_q_sz);
10472d1d418eSSumit Saxena 		bus_dmamap_load(sc->admin_reply_tag, sc->admin_reply_dmamap, sc->admin_reply, sc->admin_reply_q_sz,
104839a3e6a8SAlexander Motin 		    mpi3mr_memaddr_cb, &sc->admin_reply_phys, BUS_DMA_NOWAIT);
10492d1d418eSSumit Saxena 		mpi3mr_dprint(sc, MPI3MR_XINFO, "Admin Reply queue phys addr= %#016jx size= %d\n",
10502d1d418eSSumit Saxena 		    (uintmax_t)sc->admin_reply_phys, sc->admin_req_q_sz);
10512d1d418eSSumit Saxena 
10522d1d418eSSumit Saxena 
10532d1d418eSSumit Saxena 		if (!sc->admin_reply)
10542d1d418eSSumit Saxena 		{
10552d1d418eSSumit Saxena 			retval = -1;
10562d1d418eSSumit Saxena 			printf(IOCNAME "Memory alloc for AdminRepQ: failed\n",
10572d1d418eSSumit Saxena 			    sc->name);
10582d1d418eSSumit Saxena 			goto out_failed;
10592d1d418eSSumit Saxena 		}
10602d1d418eSSumit Saxena 	}
10612d1d418eSSumit Saxena 
10622d1d418eSSumit Saxena 	num_adm_entries = (sc->num_admin_replies << 16) |
10632d1d418eSSumit Saxena 				(sc->num_admin_reqs);
10642d1d418eSSumit Saxena 	mpi3mr_regwrite(sc, MPI3_SYSIF_ADMIN_Q_NUM_ENTRIES_OFFSET, num_adm_entries);
10652d1d418eSSumit Saxena 	mpi3mr_regwrite64(sc, MPI3_SYSIF_ADMIN_REQ_Q_ADDR_LOW_OFFSET, sc->admin_req_phys);
10662d1d418eSSumit Saxena 	mpi3mr_regwrite64(sc, MPI3_SYSIF_ADMIN_REPLY_Q_ADDR_LOW_OFFSET, sc->admin_reply_phys);
10672d1d418eSSumit Saxena 	mpi3mr_regwrite(sc, MPI3_SYSIF_ADMIN_REQ_Q_PI_OFFSET, sc->admin_req_pi);
10682d1d418eSSumit Saxena 	mpi3mr_regwrite(sc, MPI3_SYSIF_ADMIN_REPLY_Q_CI_OFFSET, sc->admin_reply_ci);
10692d1d418eSSumit Saxena 
10702d1d418eSSumit Saxena 	return retval;
10712d1d418eSSumit Saxena 
10722d1d418eSSumit Saxena out_failed:
10732d1d418eSSumit Saxena 	/* Free Admin reply*/
10742d1d418eSSumit Saxena 	if (sc->admin_reply_phys)
10752d1d418eSSumit Saxena 		bus_dmamap_unload(sc->admin_reply_tag, sc->admin_reply_dmamap);
10762d1d418eSSumit Saxena 
10772d1d418eSSumit Saxena 	if (sc->admin_reply != NULL)
10782d1d418eSSumit Saxena 		bus_dmamem_free(sc->admin_reply_tag, sc->admin_reply,
10792d1d418eSSumit Saxena 		    sc->admin_reply_dmamap);
10802d1d418eSSumit Saxena 
10812d1d418eSSumit Saxena 	if (sc->admin_reply_tag != NULL)
10822d1d418eSSumit Saxena 		bus_dma_tag_destroy(sc->admin_reply_tag);
10832d1d418eSSumit Saxena 
10842d1d418eSSumit Saxena 	/* Free Admin request*/
10852d1d418eSSumit Saxena 	if (sc->admin_req_phys)
10862d1d418eSSumit Saxena 		bus_dmamap_unload(sc->admin_req_tag, sc->admin_req_dmamap);
10872d1d418eSSumit Saxena 
10882d1d418eSSumit Saxena 	if (sc->admin_req != NULL)
10892d1d418eSSumit Saxena 		bus_dmamem_free(sc->admin_req_tag, sc->admin_req,
10902d1d418eSSumit Saxena 		    sc->admin_req_dmamap);
10912d1d418eSSumit Saxena 
10922d1d418eSSumit Saxena 	if (sc->admin_req_tag != NULL)
10932d1d418eSSumit Saxena 		bus_dma_tag_destroy(sc->admin_req_tag);
10942d1d418eSSumit Saxena 
10952d1d418eSSumit Saxena 	return retval;
10962d1d418eSSumit Saxena }
10972d1d418eSSumit Saxena 
10982d1d418eSSumit Saxena /**
10992d1d418eSSumit Saxena  * mpi3mr_print_fault_info - Display fault information
11002d1d418eSSumit Saxena  * @sc: Adapter instance reference
11012d1d418eSSumit Saxena  *
11022d1d418eSSumit Saxena  * Display the controller fault information if there is a
11032d1d418eSSumit Saxena  * controller fault.
11042d1d418eSSumit Saxena  *
11052d1d418eSSumit Saxena  * Return: Nothing.
11062d1d418eSSumit Saxena  */
mpi3mr_print_fault_info(struct mpi3mr_softc * sc)11072d1d418eSSumit Saxena static void mpi3mr_print_fault_info(struct mpi3mr_softc *sc)
11082d1d418eSSumit Saxena {
11092d1d418eSSumit Saxena 	U32 ioc_status, code, code1, code2, code3;
11102d1d418eSSumit Saxena 
11112d1d418eSSumit Saxena 	ioc_status = mpi3mr_regread(sc, MPI3_SYSIF_IOC_STATUS_OFFSET);
11122d1d418eSSumit Saxena 
11132d1d418eSSumit Saxena 	if (ioc_status & MPI3_SYSIF_IOC_STATUS_FAULT) {
11142d1d418eSSumit Saxena 		code = mpi3mr_regread(sc, MPI3_SYSIF_FAULT_OFFSET) &
11152d1d418eSSumit Saxena 			MPI3_SYSIF_FAULT_CODE_MASK;
11162d1d418eSSumit Saxena 		code1 = mpi3mr_regread(sc, MPI3_SYSIF_FAULT_INFO0_OFFSET);
11172d1d418eSSumit Saxena 		code2 = mpi3mr_regread(sc, MPI3_SYSIF_FAULT_INFO1_OFFSET);
11182d1d418eSSumit Saxena 		code3 = mpi3mr_regread(sc, MPI3_SYSIF_FAULT_INFO2_OFFSET);
11192d1d418eSSumit Saxena 		printf(IOCNAME "fault codes 0x%04x:0x%04x:0x%04x:0x%04x\n",
11202d1d418eSSumit Saxena 		    sc->name, code, code1, code2, code3);
11212d1d418eSSumit Saxena 	}
11222d1d418eSSumit Saxena }
11232d1d418eSSumit Saxena 
mpi3mr_get_iocstate(struct mpi3mr_softc * sc)11242d1d418eSSumit Saxena enum mpi3mr_iocstate mpi3mr_get_iocstate(struct mpi3mr_softc *sc)
11252d1d418eSSumit Saxena {
11262d1d418eSSumit Saxena 	U32 ioc_status, ioc_control;
11272d1d418eSSumit Saxena 	U8 ready, enabled;
11282d1d418eSSumit Saxena 
11292d1d418eSSumit Saxena 	ioc_status = mpi3mr_regread(sc, MPI3_SYSIF_IOC_STATUS_OFFSET);
11302d1d418eSSumit Saxena 	ioc_control = mpi3mr_regread(sc, MPI3_SYSIF_IOC_CONFIG_OFFSET);
11312d1d418eSSumit Saxena 
11322d1d418eSSumit Saxena 	if(sc->unrecoverable)
11332d1d418eSSumit Saxena 		return MRIOC_STATE_UNRECOVERABLE;
11342d1d418eSSumit Saxena 	if (ioc_status & MPI3_SYSIF_IOC_STATUS_FAULT)
11352d1d418eSSumit Saxena 		return MRIOC_STATE_FAULT;
11362d1d418eSSumit Saxena 
11372d1d418eSSumit Saxena 	ready = (ioc_status & MPI3_SYSIF_IOC_STATUS_READY);
11382d1d418eSSumit Saxena 	enabled = (ioc_control & MPI3_SYSIF_IOC_CONFIG_ENABLE_IOC);
11392d1d418eSSumit Saxena 
11402d1d418eSSumit Saxena 	if (ready && enabled)
11412d1d418eSSumit Saxena 		return MRIOC_STATE_READY;
11422d1d418eSSumit Saxena 	if ((!ready) && (!enabled))
11432d1d418eSSumit Saxena 		return MRIOC_STATE_RESET;
11442d1d418eSSumit Saxena 	if ((!ready) && (enabled))
11452d1d418eSSumit Saxena 		return MRIOC_STATE_BECOMING_READY;
11462d1d418eSSumit Saxena 
11472d1d418eSSumit Saxena 	return MRIOC_STATE_RESET_REQUESTED;
11482d1d418eSSumit Saxena }
11492d1d418eSSumit Saxena 
mpi3mr_clear_resethistory(struct mpi3mr_softc * sc)11502d1d418eSSumit Saxena static inline void mpi3mr_clear_resethistory(struct mpi3mr_softc *sc)
11512d1d418eSSumit Saxena {
11522d1d418eSSumit Saxena         U32 ioc_status;
11532d1d418eSSumit Saxena 
11542d1d418eSSumit Saxena 	ioc_status = mpi3mr_regread(sc, MPI3_SYSIF_IOC_STATUS_OFFSET);
11552d1d418eSSumit Saxena         if (ioc_status & MPI3_SYSIF_IOC_STATUS_RESET_HISTORY)
11562d1d418eSSumit Saxena 		mpi3mr_regwrite(sc, MPI3_SYSIF_IOC_STATUS_OFFSET, ioc_status);
11572d1d418eSSumit Saxena 
11582d1d418eSSumit Saxena }
11592d1d418eSSumit Saxena 
11602d1d418eSSumit Saxena /**
11612d1d418eSSumit Saxena  * mpi3mr_mur_ioc - Message unit Reset handler
11622d1d418eSSumit Saxena  * @sc: Adapter instance reference
11632d1d418eSSumit Saxena  * @reset_reason: Reset reason code
11642d1d418eSSumit Saxena  *
11652d1d418eSSumit Saxena  * Issue Message unit Reset to the controller and wait for it to
11662d1d418eSSumit Saxena  * be complete.
11672d1d418eSSumit Saxena  *
11682d1d418eSSumit Saxena  * Return: 0 on success, -1 on failure.
11692d1d418eSSumit Saxena  */
mpi3mr_mur_ioc(struct mpi3mr_softc * sc,U16 reset_reason)11703012fa8fSChandrakanth patil static int mpi3mr_mur_ioc(struct mpi3mr_softc *sc, U16 reset_reason)
11712d1d418eSSumit Saxena {
11723012fa8fSChandrakanth patil 	U32 ioc_config, timeout, ioc_status, scratch_pad0;
11732d1d418eSSumit Saxena         int retval = -1;
11742d1d418eSSumit Saxena 
11752d1d418eSSumit Saxena         mpi3mr_dprint(sc, MPI3MR_INFO, "Issuing Message Unit Reset(MUR)\n");
11762d1d418eSSumit Saxena         if (sc->unrecoverable) {
11772d1d418eSSumit Saxena                 mpi3mr_dprint(sc, MPI3MR_ERROR, "IOC is unrecoverable MUR not issued\n");
11782d1d418eSSumit Saxena                 return retval;
11792d1d418eSSumit Saxena         }
11802d1d418eSSumit Saxena         mpi3mr_clear_resethistory(sc);
11813012fa8fSChandrakanth patil 
11823012fa8fSChandrakanth patil 	scratch_pad0 = ((MPI3MR_RESET_REASON_OSTYPE_FREEBSD <<
11833012fa8fSChandrakanth patil 			MPI3MR_RESET_REASON_OSTYPE_SHIFT) |
11843012fa8fSChandrakanth patil 			(sc->facts.ioc_num <<
11853012fa8fSChandrakanth patil 			MPI3MR_RESET_REASON_IOCNUM_SHIFT) | reset_reason);
11863012fa8fSChandrakanth patil 	mpi3mr_regwrite(sc, MPI3_SYSIF_SCRATCHPAD0_OFFSET, scratch_pad0);
11872d1d418eSSumit Saxena 	ioc_config = mpi3mr_regread(sc, MPI3_SYSIF_IOC_CONFIG_OFFSET);
11882d1d418eSSumit Saxena         ioc_config &= ~MPI3_SYSIF_IOC_CONFIG_ENABLE_IOC;
11892d1d418eSSumit Saxena 	mpi3mr_regwrite(sc, MPI3_SYSIF_IOC_CONFIG_OFFSET, ioc_config);
11902d1d418eSSumit Saxena 
11912d1d418eSSumit Saxena         timeout = MPI3MR_MUR_TIMEOUT * 10;
11922d1d418eSSumit Saxena         do {
11932d1d418eSSumit Saxena 		ioc_status = mpi3mr_regread(sc, MPI3_SYSIF_IOC_STATUS_OFFSET);
11942d1d418eSSumit Saxena                 if ((ioc_status & MPI3_SYSIF_IOC_STATUS_RESET_HISTORY)) {
11952d1d418eSSumit Saxena                         mpi3mr_clear_resethistory(sc);
11962d1d418eSSumit Saxena 			ioc_config =
11972d1d418eSSumit Saxena 				mpi3mr_regread(sc, MPI3_SYSIF_IOC_CONFIG_OFFSET);
11982d1d418eSSumit Saxena                         if (!((ioc_status & MPI3_SYSIF_IOC_STATUS_READY) ||
11992d1d418eSSumit Saxena                             (ioc_status & MPI3_SYSIF_IOC_STATUS_FAULT) ||
12002d1d418eSSumit Saxena                             (ioc_config & MPI3_SYSIF_IOC_CONFIG_ENABLE_IOC))) {
12012d1d418eSSumit Saxena                                 retval = 0;
12022d1d418eSSumit Saxena                                 break;
12032d1d418eSSumit Saxena                         }
12042d1d418eSSumit Saxena                 }
12052d1d418eSSumit Saxena                 DELAY(100 * 1000);
12062d1d418eSSumit Saxena         } while (--timeout);
12072d1d418eSSumit Saxena 
12082d1d418eSSumit Saxena 	ioc_status = mpi3mr_regread(sc, MPI3_SYSIF_IOC_STATUS_OFFSET);
12092d1d418eSSumit Saxena 	ioc_config = mpi3mr_regread(sc, MPI3_SYSIF_IOC_CONFIG_OFFSET);
12102d1d418eSSumit Saxena 
12112d1d418eSSumit Saxena         mpi3mr_dprint(sc, MPI3MR_INFO, "IOC Status/Config after %s MUR is (0x%x)/(0x%x)\n",
12122d1d418eSSumit Saxena                 !retval ? "successful":"failed", ioc_status, ioc_config);
12132d1d418eSSumit Saxena         return retval;
12142d1d418eSSumit Saxena }
12152d1d418eSSumit Saxena 
12162d1d418eSSumit Saxena /**
12172d1d418eSSumit Saxena  * mpi3mr_bring_ioc_ready - Bring controller to ready state
12182d1d418eSSumit Saxena  * @sc: Adapter instance reference
12192d1d418eSSumit Saxena  *
12202d1d418eSSumit Saxena  * Set Enable IOC bit in IOC configuration register and wait for
12212d1d418eSSumit Saxena  * the controller to become ready.
12222d1d418eSSumit Saxena  *
12232d1d418eSSumit Saxena  * Return: 0 on success, appropriate error on failure.
12242d1d418eSSumit Saxena  */
mpi3mr_bring_ioc_ready(struct mpi3mr_softc * sc)12252d1d418eSSumit Saxena static int mpi3mr_bring_ioc_ready(struct mpi3mr_softc *sc)
12262d1d418eSSumit Saxena {
12272d1d418eSSumit Saxena         U32 ioc_config, timeout;
12282d1d418eSSumit Saxena         enum mpi3mr_iocstate current_state;
12292d1d418eSSumit Saxena 
12302d1d418eSSumit Saxena 	ioc_config = mpi3mr_regread(sc, MPI3_SYSIF_IOC_CONFIG_OFFSET);
12312d1d418eSSumit Saxena         ioc_config |= MPI3_SYSIF_IOC_CONFIG_ENABLE_IOC;
12322d1d418eSSumit Saxena 	mpi3mr_regwrite(sc, MPI3_SYSIF_IOC_CONFIG_OFFSET, ioc_config);
12332d1d418eSSumit Saxena 
12342d1d418eSSumit Saxena         timeout = sc->ready_timeout * 10;
12352d1d418eSSumit Saxena         do {
12362d1d418eSSumit Saxena                 current_state = mpi3mr_get_iocstate(sc);
12372d1d418eSSumit Saxena                 if (current_state == MRIOC_STATE_READY)
12382d1d418eSSumit Saxena                         return 0;
12392d1d418eSSumit Saxena                 DELAY(100 * 1000);
12402d1d418eSSumit Saxena         } while (--timeout);
12412d1d418eSSumit Saxena 
12422d1d418eSSumit Saxena         return -1;
12432d1d418eSSumit Saxena }
12442d1d418eSSumit Saxena 
12452d1d418eSSumit Saxena static const struct {
12462d1d418eSSumit Saxena 	enum mpi3mr_iocstate value;
12472d1d418eSSumit Saxena 	char *name;
12482d1d418eSSumit Saxena } mrioc_states[] = {
12492d1d418eSSumit Saxena 	{ MRIOC_STATE_READY, "ready" },
12502d1d418eSSumit Saxena 	{ MRIOC_STATE_FAULT, "fault" },
12512d1d418eSSumit Saxena 	{ MRIOC_STATE_RESET, "reset" },
12522d1d418eSSumit Saxena 	{ MRIOC_STATE_BECOMING_READY, "becoming ready" },
12532d1d418eSSumit Saxena 	{ MRIOC_STATE_RESET_REQUESTED, "reset requested" },
12542d1d418eSSumit Saxena 	{ MRIOC_STATE_COUNT, "Count" },
12552d1d418eSSumit Saxena };
12562d1d418eSSumit Saxena 
mpi3mr_iocstate_name(enum mpi3mr_iocstate mrioc_state)12572d1d418eSSumit Saxena static const char *mpi3mr_iocstate_name(enum mpi3mr_iocstate mrioc_state)
12582d1d418eSSumit Saxena {
12592d1d418eSSumit Saxena 	int i;
12602d1d418eSSumit Saxena 	char *name = NULL;
12612d1d418eSSumit Saxena 
12622d1d418eSSumit Saxena 	for (i = 0; i < MRIOC_STATE_COUNT; i++) {
12632d1d418eSSumit Saxena 		if (mrioc_states[i].value == mrioc_state){
12642d1d418eSSumit Saxena 			name = mrioc_states[i].name;
12652d1d418eSSumit Saxena 			break;
12662d1d418eSSumit Saxena 		}
12672d1d418eSSumit Saxena 	}
12682d1d418eSSumit Saxena 	return name;
12692d1d418eSSumit Saxena }
12702d1d418eSSumit Saxena 
12712d1d418eSSumit Saxena /* Reset reason to name mapper structure*/
12722d1d418eSSumit Saxena static const struct {
12732d1d418eSSumit Saxena 	enum mpi3mr_reset_reason value;
12742d1d418eSSumit Saxena 	char *name;
12752d1d418eSSumit Saxena } mpi3mr_reset_reason_codes[] = {
12762d1d418eSSumit Saxena 	{ MPI3MR_RESET_FROM_BRINGUP, "timeout in bringup" },
12772d1d418eSSumit Saxena 	{ MPI3MR_RESET_FROM_FAULT_WATCH, "fault" },
12782d1d418eSSumit Saxena 	{ MPI3MR_RESET_FROM_IOCTL, "application" },
12792d1d418eSSumit Saxena 	{ MPI3MR_RESET_FROM_EH_HOS, "error handling" },
12802d1d418eSSumit Saxena 	{ MPI3MR_RESET_FROM_TM_TIMEOUT, "TM timeout" },
12812d1d418eSSumit Saxena 	{ MPI3MR_RESET_FROM_IOCTL_TIMEOUT, "IOCTL timeout" },
12822d1d418eSSumit Saxena 	{ MPI3MR_RESET_FROM_SCSIIO_TIMEOUT, "SCSIIO timeout" },
12832d1d418eSSumit Saxena 	{ MPI3MR_RESET_FROM_MUR_FAILURE, "MUR failure" },
12842d1d418eSSumit Saxena 	{ MPI3MR_RESET_FROM_CTLR_CLEANUP, "timeout in controller cleanup" },
12852d1d418eSSumit Saxena 	{ MPI3MR_RESET_FROM_CIACTIV_FAULT, "component image activation fault" },
12862d1d418eSSumit Saxena 	{ MPI3MR_RESET_FROM_PE_TIMEOUT, "port enable timeout" },
12872d1d418eSSumit Saxena 	{ MPI3MR_RESET_FROM_TSU_TIMEOUT, "time stamp update timeout" },
12882d1d418eSSumit Saxena 	{ MPI3MR_RESET_FROM_DELREQQ_TIMEOUT, "delete request queue timeout" },
12892d1d418eSSumit Saxena 	{ MPI3MR_RESET_FROM_DELREPQ_TIMEOUT, "delete reply queue timeout" },
12902d1d418eSSumit Saxena 	{
12912d1d418eSSumit Saxena 		MPI3MR_RESET_FROM_CREATEREPQ_TIMEOUT,
12922d1d418eSSumit Saxena 		"create request queue timeout"
12932d1d418eSSumit Saxena 	},
12942d1d418eSSumit Saxena 	{
12952d1d418eSSumit Saxena 		MPI3MR_RESET_FROM_CREATEREQQ_TIMEOUT,
12962d1d418eSSumit Saxena 		"create reply queue timeout"
12972d1d418eSSumit Saxena 	},
12982d1d418eSSumit Saxena 	{ MPI3MR_RESET_FROM_IOCFACTS_TIMEOUT, "IOC facts timeout" },
12992d1d418eSSumit Saxena 	{ MPI3MR_RESET_FROM_IOCINIT_TIMEOUT, "IOC init timeout" },
13002d1d418eSSumit Saxena 	{ MPI3MR_RESET_FROM_EVTNOTIFY_TIMEOUT, "event notify timeout" },
13012d1d418eSSumit Saxena 	{ MPI3MR_RESET_FROM_EVTACK_TIMEOUT, "event acknowledgment timeout" },
13022d1d418eSSumit Saxena 	{
13032d1d418eSSumit Saxena 		MPI3MR_RESET_FROM_CIACTVRST_TIMER,
13042d1d418eSSumit Saxena 		"component image activation timeout"
13052d1d418eSSumit Saxena 	},
13062d1d418eSSumit Saxena 	{
13072d1d418eSSumit Saxena 		MPI3MR_RESET_FROM_GETPKGVER_TIMEOUT,
13082d1d418eSSumit Saxena 		"get package version timeout"
13092d1d418eSSumit Saxena 	},
13102d1d418eSSumit Saxena 	{
13112d1d418eSSumit Saxena 		MPI3MR_RESET_FROM_PELABORT_TIMEOUT,
13122d1d418eSSumit Saxena 		"persistent event log abort timeout"
13132d1d418eSSumit Saxena 	},
13142d1d418eSSumit Saxena 	{ MPI3MR_RESET_FROM_SYSFS, "sysfs invocation" },
13152d1d418eSSumit Saxena 	{ MPI3MR_RESET_FROM_SYSFS_TIMEOUT, "sysfs TM timeout" },
13162d1d418eSSumit Saxena 	{
13172d1d418eSSumit Saxena 		MPI3MR_RESET_FROM_DIAG_BUFFER_POST_TIMEOUT,
13182d1d418eSSumit Saxena 		"diagnostic buffer post timeout"
13192d1d418eSSumit Saxena 	},
13202d1d418eSSumit Saxena 	{ MPI3MR_RESET_FROM_FIRMWARE, "firmware asynchronus reset" },
13212d1d418eSSumit Saxena 	{ MPI3MR_RESET_REASON_COUNT, "Reset reason count" },
13222d1d418eSSumit Saxena };
13232d1d418eSSumit Saxena 
13242d1d418eSSumit Saxena /**
13252d1d418eSSumit Saxena  * mpi3mr_reset_rc_name - get reset reason code name
13262d1d418eSSumit Saxena  * @reason_code: reset reason code value
13272d1d418eSSumit Saxena  *
13282d1d418eSSumit Saxena  * Map reset reason to an NULL terminated ASCII string
13292d1d418eSSumit Saxena  *
13302d1d418eSSumit Saxena  * Return: Name corresponding to reset reason value or NULL.
13312d1d418eSSumit Saxena  */
mpi3mr_reset_rc_name(enum mpi3mr_reset_reason reason_code)13322d1d418eSSumit Saxena static const char *mpi3mr_reset_rc_name(enum mpi3mr_reset_reason reason_code)
13332d1d418eSSumit Saxena {
13342d1d418eSSumit Saxena 	int i;
13352d1d418eSSumit Saxena 	char *name = NULL;
13362d1d418eSSumit Saxena 
13372d1d418eSSumit Saxena 	for (i = 0; i < MPI3MR_RESET_REASON_COUNT; i++) {
13382d1d418eSSumit Saxena 		if (mpi3mr_reset_reason_codes[i].value == reason_code) {
13392d1d418eSSumit Saxena 			name = mpi3mr_reset_reason_codes[i].name;
13402d1d418eSSumit Saxena 			break;
13412d1d418eSSumit Saxena 		}
13422d1d418eSSumit Saxena 	}
13432d1d418eSSumit Saxena 	return name;
13442d1d418eSSumit Saxena }
13452d1d418eSSumit Saxena 
13462d1d418eSSumit Saxena #define MAX_RESET_TYPE 3
13472d1d418eSSumit Saxena /* Reset type to name mapper structure*/
13482d1d418eSSumit Saxena static const struct {
13492d1d418eSSumit Saxena 	U16 reset_type;
13502d1d418eSSumit Saxena 	char *name;
13512d1d418eSSumit Saxena } mpi3mr_reset_types[] = {
13522d1d418eSSumit Saxena 	{ MPI3_SYSIF_HOST_DIAG_RESET_ACTION_SOFT_RESET, "soft" },
13532d1d418eSSumit Saxena 	{ MPI3_SYSIF_HOST_DIAG_RESET_ACTION_DIAG_FAULT, "diag fault" },
13542d1d418eSSumit Saxena 	{ MAX_RESET_TYPE, "count"}
13552d1d418eSSumit Saxena };
13562d1d418eSSumit Saxena 
13572d1d418eSSumit Saxena /**
13582d1d418eSSumit Saxena  * mpi3mr_reset_type_name - get reset type name
13592d1d418eSSumit Saxena  * @reset_type: reset type value
13602d1d418eSSumit Saxena  *
13612d1d418eSSumit Saxena  * Map reset type to an NULL terminated ASCII string
13622d1d418eSSumit Saxena  *
13632d1d418eSSumit Saxena  * Return: Name corresponding to reset type value or NULL.
13642d1d418eSSumit Saxena  */
mpi3mr_reset_type_name(U16 reset_type)13652d1d418eSSumit Saxena static const char *mpi3mr_reset_type_name(U16 reset_type)
13662d1d418eSSumit Saxena {
13672d1d418eSSumit Saxena 	int i;
13682d1d418eSSumit Saxena 	char *name = NULL;
13692d1d418eSSumit Saxena 
13702d1d418eSSumit Saxena 	for (i = 0; i < MAX_RESET_TYPE; i++) {
13712d1d418eSSumit Saxena 		if (mpi3mr_reset_types[i].reset_type == reset_type) {
13722d1d418eSSumit Saxena 			name = mpi3mr_reset_types[i].name;
13732d1d418eSSumit Saxena 			break;
13742d1d418eSSumit Saxena 		}
13752d1d418eSSumit Saxena 	}
13762d1d418eSSumit Saxena 	return name;
13772d1d418eSSumit Saxena }
13782d1d418eSSumit Saxena 
13792d1d418eSSumit Saxena /**
13802d1d418eSSumit Saxena  * mpi3mr_soft_reset_success - Check softreset is success or not
13812d1d418eSSumit Saxena  * @ioc_status: IOC status register value
13822d1d418eSSumit Saxena  * @ioc_config: IOC config register value
13832d1d418eSSumit Saxena  *
13842d1d418eSSumit Saxena  * Check whether the soft reset is successful or not based on
13852d1d418eSSumit Saxena  * IOC status and IOC config register values.
13862d1d418eSSumit Saxena  *
13872d1d418eSSumit Saxena  * Return: True when the soft reset is success, false otherwise.
13882d1d418eSSumit Saxena  */
13892d1d418eSSumit Saxena static inline bool
mpi3mr_soft_reset_success(U32 ioc_status,U32 ioc_config)13902d1d418eSSumit Saxena mpi3mr_soft_reset_success(U32 ioc_status, U32 ioc_config)
13912d1d418eSSumit Saxena {
13922d1d418eSSumit Saxena 	if (!((ioc_status & MPI3_SYSIF_IOC_STATUS_READY) ||
13932d1d418eSSumit Saxena 	    (ioc_status & MPI3_SYSIF_IOC_STATUS_FAULT) ||
13942d1d418eSSumit Saxena 	    (ioc_config & MPI3_SYSIF_IOC_CONFIG_ENABLE_IOC)))
13952d1d418eSSumit Saxena 		return true;
13962d1d418eSSumit Saxena 	return false;
13972d1d418eSSumit Saxena }
13982d1d418eSSumit Saxena 
13992d1d418eSSumit Saxena /**
14002d1d418eSSumit Saxena  * mpi3mr_diagfault_success - Check diag fault is success or not
14012d1d418eSSumit Saxena  * @sc: Adapter reference
14022d1d418eSSumit Saxena  * @ioc_status: IOC status register value
14032d1d418eSSumit Saxena  *
14042d1d418eSSumit Saxena  * Check whether the controller hit diag reset fault code.
14052d1d418eSSumit Saxena  *
14062d1d418eSSumit Saxena  * Return: True when there is diag fault, false otherwise.
14072d1d418eSSumit Saxena  */
mpi3mr_diagfault_success(struct mpi3mr_softc * sc,U32 ioc_status)14082d1d418eSSumit Saxena static inline bool mpi3mr_diagfault_success(struct mpi3mr_softc *sc,
14092d1d418eSSumit Saxena 	U32 ioc_status)
14102d1d418eSSumit Saxena {
14112d1d418eSSumit Saxena 	if (!(ioc_status & MPI3_SYSIF_IOC_STATUS_FAULT))
14122d1d418eSSumit Saxena 		return false;
14134034d706SChandrakanth patil 	mpi3mr_print_fault_info(sc);
14142d1d418eSSumit Saxena 	return true;
14152d1d418eSSumit Saxena }
14162d1d418eSSumit Saxena 
14172d1d418eSSumit Saxena /**
14182d1d418eSSumit Saxena  * mpi3mr_issue_iocfacts - Send IOC Facts
14192d1d418eSSumit Saxena  * @sc: Adapter instance reference
14202d1d418eSSumit Saxena  * @facts_data: Cached IOC facts data
14212d1d418eSSumit Saxena  *
14222d1d418eSSumit Saxena  * Issue IOC Facts MPI request through admin queue and wait for
14232d1d418eSSumit Saxena  * the completion of it or time out.
14242d1d418eSSumit Saxena  *
14252d1d418eSSumit Saxena  * Return: 0 on success, non-zero on failures.
14262d1d418eSSumit Saxena  */
mpi3mr_issue_iocfacts(struct mpi3mr_softc * sc,Mpi3IOCFactsData_t * facts_data)14272d1d418eSSumit Saxena static int mpi3mr_issue_iocfacts(struct mpi3mr_softc *sc,
14282d1d418eSSumit Saxena     Mpi3IOCFactsData_t *facts_data)
14292d1d418eSSumit Saxena {
14302d1d418eSSumit Saxena 	Mpi3IOCFactsRequest_t iocfacts_req;
14312d1d418eSSumit Saxena 	bus_dma_tag_t data_tag = NULL;
14322d1d418eSSumit Saxena 	bus_dmamap_t data_map = NULL;
14332d1d418eSSumit Saxena 	bus_addr_t data_phys = 0;
14342d1d418eSSumit Saxena 	void *data = NULL;
14352d1d418eSSumit Saxena 	U32 data_len = sizeof(*facts_data);
14362d1d418eSSumit Saxena 	int retval = 0;
14372d1d418eSSumit Saxena 
14382d1d418eSSumit Saxena 	U8 sgl_flags = (MPI3_SGE_FLAGS_ELEMENT_TYPE_SIMPLE |
14392d1d418eSSumit Saxena                 	MPI3_SGE_FLAGS_DLAS_SYSTEM |
14402d1d418eSSumit Saxena 			MPI3_SGE_FLAGS_END_OF_LIST);
14412d1d418eSSumit Saxena 
14422d1d418eSSumit Saxena 
144391d96135SWarner Losh 	/*
14441ec7c672SWarner Losh 	 * We can't use sc->dma_loaddr here.  We set those only after we get the
14451ec7c672SWarner Losh 	 * iocfacts.  So allocate in the lower 4GB.  The amount of data is tiny
14461ec7c672SWarner Losh 	 * and we don't do this that often, so any bouncing we might have to do
14471ec7c672SWarner Losh 	 * isn't a cause for concern.
144891d96135SWarner Losh 	 */
14492d1d418eSSumit Saxena         if (bus_dma_tag_create(sc->mpi3mr_parent_dmat,    /* parent */
14502d1d418eSSumit Saxena 				4, 0,			/* algnmnt, boundary */
14512d1d418eSSumit Saxena 				BUS_SPACE_MAXADDR_32BIT,/* lowaddr */
14522d1d418eSSumit Saxena 				BUS_SPACE_MAXADDR,	/* highaddr */
14532d1d418eSSumit Saxena 				NULL, NULL,		/* filter, filterarg */
14542d1d418eSSumit Saxena                                 data_len,		/* maxsize */
14552d1d418eSSumit Saxena                                 1,			/* nsegments */
14562d1d418eSSumit Saxena                                 data_len,		/* maxsegsize */
14572d1d418eSSumit Saxena                                 0,			/* flags */
14582d1d418eSSumit Saxena                                 NULL, NULL,		/* lockfunc, lockarg */
14592d1d418eSSumit Saxena                                 &data_tag)) {
14602d1d418eSSumit Saxena 		mpi3mr_dprint(sc, MPI3MR_ERROR, "Cannot allocate request DMA tag\n");
14612d1d418eSSumit Saxena 		return (ENOMEM);
14622d1d418eSSumit Saxena         }
14632d1d418eSSumit Saxena 
14642d1d418eSSumit Saxena         if (bus_dmamem_alloc(data_tag, (void **)&data,
14652d1d418eSSumit Saxena 	    BUS_DMA_NOWAIT, &data_map)) {
14662d1d418eSSumit Saxena 		mpi3mr_dprint(sc, MPI3MR_ERROR, "Func: %s line: %d Data  DMA mem alloc failed\n",
14672d1d418eSSumit Saxena 			__func__, __LINE__);
14682d1d418eSSumit Saxena 		return (ENOMEM);
14692d1d418eSSumit Saxena         }
14702d1d418eSSumit Saxena 
14712d1d418eSSumit Saxena         bzero(data, data_len);
14722d1d418eSSumit Saxena         bus_dmamap_load(data_tag, data_map, data, data_len,
147339a3e6a8SAlexander Motin 	    mpi3mr_memaddr_cb, &data_phys, BUS_DMA_NOWAIT);
14742d1d418eSSumit Saxena 	mpi3mr_dprint(sc, MPI3MR_XINFO, "Func: %s line: %d IOCfacts data phys addr= %#016jx size= %d\n",
14752d1d418eSSumit Saxena 	    __func__, __LINE__, (uintmax_t)data_phys, data_len);
14762d1d418eSSumit Saxena 
14772d1d418eSSumit Saxena 	if (!data)
14782d1d418eSSumit Saxena 	{
14792d1d418eSSumit Saxena 		retval = -1;
14802d1d418eSSumit Saxena 		printf(IOCNAME "Memory alloc for IOCFactsData: failed\n",
14812d1d418eSSumit Saxena 		    sc->name);
14822d1d418eSSumit Saxena 		goto out;
14832d1d418eSSumit Saxena 	}
14842d1d418eSSumit Saxena 
14852d1d418eSSumit Saxena 	mtx_lock(&sc->init_cmds.completion.lock);
14862d1d418eSSumit Saxena 	memset(&iocfacts_req, 0, sizeof(iocfacts_req));
14872d1d418eSSumit Saxena 
14882d1d418eSSumit Saxena 	if (sc->init_cmds.state & MPI3MR_CMD_PENDING) {
14892d1d418eSSumit Saxena 		retval = -1;
14902d1d418eSSumit Saxena 		printf(IOCNAME "Issue IOCFacts: Init command is in use\n",
14912d1d418eSSumit Saxena 		    sc->name);
14922d1d418eSSumit Saxena 		mtx_unlock(&sc->init_cmds.completion.lock);
14932d1d418eSSumit Saxena 		goto out;
14942d1d418eSSumit Saxena 	}
14952d1d418eSSumit Saxena 
14962d1d418eSSumit Saxena 	sc->init_cmds.state = MPI3MR_CMD_PENDING;
14972d1d418eSSumit Saxena 	sc->init_cmds.is_waiting = 1;
14982d1d418eSSumit Saxena 	sc->init_cmds.callback = NULL;
14992d1d418eSSumit Saxena 	iocfacts_req.HostTag = (MPI3MR_HOSTTAG_INITCMDS);
15002d1d418eSSumit Saxena 	iocfacts_req.Function = MPI3_FUNCTION_IOC_FACTS;
15012d1d418eSSumit Saxena 
15022d1d418eSSumit Saxena 	mpi3mr_add_sg_single(&iocfacts_req.SGL, sgl_flags, data_len,
15032d1d418eSSumit Saxena 	    data_phys);
15042d1d418eSSumit Saxena 
15052d1d418eSSumit Saxena 	init_completion(&sc->init_cmds.completion);
15062d1d418eSSumit Saxena 
15072d1d418eSSumit Saxena 	retval = mpi3mr_submit_admin_cmd(sc, &iocfacts_req,
15082d1d418eSSumit Saxena 	    sizeof(iocfacts_req));
15092d1d418eSSumit Saxena 
15102d1d418eSSumit Saxena 	if (retval) {
15112d1d418eSSumit Saxena 		printf(IOCNAME "Issue IOCFacts: Admin Post failed\n",
15122d1d418eSSumit Saxena 		    sc->name);
15132d1d418eSSumit Saxena 		goto out_unlock;
15142d1d418eSSumit Saxena 	}
15152d1d418eSSumit Saxena 
15162d1d418eSSumit Saxena 	wait_for_completion_timeout(&sc->init_cmds.completion,
15172d1d418eSSumit Saxena 	    (MPI3MR_INTADMCMD_TIMEOUT));
15182d1d418eSSumit Saxena 	if (!(sc->init_cmds.state & MPI3MR_CMD_COMPLETE)) {
15192d1d418eSSumit Saxena 		printf(IOCNAME "Issue IOCFacts: command timed out\n",
15202d1d418eSSumit Saxena 		    sc->name);
15212d1d418eSSumit Saxena 		mpi3mr_check_rh_fault_ioc(sc,
15222d1d418eSSumit Saxena 		    MPI3MR_RESET_FROM_IOCFACTS_TIMEOUT);
15232d1d418eSSumit Saxena 		sc->unrecoverable = 1;
15242d1d418eSSumit Saxena 		retval = -1;
15252d1d418eSSumit Saxena 		goto out_unlock;
15262d1d418eSSumit Saxena 	}
15272d1d418eSSumit Saxena 
15282d1d418eSSumit Saxena 	if ((sc->init_cmds.ioc_status & MPI3_IOCSTATUS_STATUS_MASK)
15292d1d418eSSumit Saxena 	     != MPI3_IOCSTATUS_SUCCESS ) {
15302d1d418eSSumit Saxena 		printf(IOCNAME "Issue IOCFacts: Failed IOCStatus(0x%04x) "
15312d1d418eSSumit Saxena 		    " Loginfo(0x%08x) \n" , sc->name,
15322d1d418eSSumit Saxena 		    (sc->init_cmds.ioc_status & MPI3_IOCSTATUS_STATUS_MASK),
15332d1d418eSSumit Saxena 		    sc->init_cmds.ioc_loginfo);
15342d1d418eSSumit Saxena 		retval = -1;
15352d1d418eSSumit Saxena 		goto out_unlock;
15362d1d418eSSumit Saxena 	}
15372d1d418eSSumit Saxena 
15382d1d418eSSumit Saxena 	memcpy(facts_data, (U8 *)data, data_len);
15392d1d418eSSumit Saxena out_unlock:
15402d1d418eSSumit Saxena 	sc->init_cmds.state = MPI3MR_CMD_NOTUSED;
15412d1d418eSSumit Saxena 	mtx_unlock(&sc->init_cmds.completion.lock);
15422d1d418eSSumit Saxena 
15432d1d418eSSumit Saxena out:
15442d1d418eSSumit Saxena 	if (data_phys != 0)
15452d1d418eSSumit Saxena 		bus_dmamap_unload(data_tag, data_map);
15462d1d418eSSumit Saxena 	if (data != NULL)
15472d1d418eSSumit Saxena 		bus_dmamem_free(data_tag, data, data_map);
15482d1d418eSSumit Saxena 	if (data_tag != NULL)
15492d1d418eSSumit Saxena 		bus_dma_tag_destroy(data_tag);
15502d1d418eSSumit Saxena 	return retval;
15512d1d418eSSumit Saxena }
15522d1d418eSSumit Saxena 
15532d1d418eSSumit Saxena /**
15542d1d418eSSumit Saxena  * mpi3mr_process_factsdata - Process IOC facts data
15552d1d418eSSumit Saxena  * @sc: Adapter instance reference
15562d1d418eSSumit Saxena  * @facts_data: Cached IOC facts data
15572d1d418eSSumit Saxena  *
15582d1d418eSSumit Saxena  * Convert IOC facts data into cpu endianness and cache it in
15592d1d418eSSumit Saxena  * the driver .
15602d1d418eSSumit Saxena  *
15612d1d418eSSumit Saxena  * Return: Nothing.
15622d1d418eSSumit Saxena  */
mpi3mr_process_factsdata(struct mpi3mr_softc * sc,Mpi3IOCFactsData_t * facts_data)15632d1d418eSSumit Saxena static int mpi3mr_process_factsdata(struct mpi3mr_softc *sc,
15642d1d418eSSumit Saxena     Mpi3IOCFactsData_t *facts_data)
15652d1d418eSSumit Saxena {
15662d1d418eSSumit Saxena 	int retval = 0;
15672d1d418eSSumit Saxena 	U32 ioc_config, req_sz, facts_flags;
156828a27434SWarner Losh         struct mpi3mr_compimg_ver *fwver;
15692d1d418eSSumit Saxena 
15702d1d418eSSumit Saxena 	if (le16toh(facts_data->IOCFactsDataLength) !=
15712d1d418eSSumit Saxena 	    (sizeof(*facts_data) / 4)) {
15722d1d418eSSumit Saxena 		mpi3mr_dprint(sc, MPI3MR_INFO, "IOCFacts data length mismatch "
15732d1d418eSSumit Saxena 		    " driver_sz(%ld) firmware_sz(%d) \n",
15742d1d418eSSumit Saxena 		    sizeof(*facts_data),
15752d1d418eSSumit Saxena 		    facts_data->IOCFactsDataLength);
15762d1d418eSSumit Saxena 	}
15772d1d418eSSumit Saxena 
15782d1d418eSSumit Saxena 	ioc_config = mpi3mr_regread(sc, MPI3_SYSIF_IOC_CONFIG_OFFSET);
15792d1d418eSSumit Saxena         req_sz = 1 << ((ioc_config & MPI3_SYSIF_IOC_CONFIG_OPER_REQ_ENT_SZ) >>
15802d1d418eSSumit Saxena                   MPI3_SYSIF_IOC_CONFIG_OPER_REQ_ENT_SZ_SHIFT);
15812d1d418eSSumit Saxena 
15822d1d418eSSumit Saxena 	if (facts_data->IOCRequestFrameSize != (req_sz/4)) {
15832d1d418eSSumit Saxena 		 mpi3mr_dprint(sc, MPI3MR_INFO, "IOCFacts data reqFrameSize mismatch "
15842d1d418eSSumit Saxena 		    " hw_size(%d) firmware_sz(%d) \n" , req_sz/4,
15852d1d418eSSumit Saxena 		    facts_data->IOCRequestFrameSize);
15862d1d418eSSumit Saxena 	}
15872d1d418eSSumit Saxena 
15882d1d418eSSumit Saxena 	memset(&sc->facts, 0, sizeof(sc->facts));
15892d1d418eSSumit Saxena 
15902d1d418eSSumit Saxena 	facts_flags = le32toh(facts_data->Flags);
15912d1d418eSSumit Saxena 	sc->facts.op_req_sz = req_sz;
15922d1d418eSSumit Saxena 	sc->op_reply_sz = 1 << ((ioc_config &
15932d1d418eSSumit Saxena                                   MPI3_SYSIF_IOC_CONFIG_OPER_RPY_ENT_SZ) >>
15942d1d418eSSumit Saxena                                   MPI3_SYSIF_IOC_CONFIG_OPER_RPY_ENT_SZ_SHIFT);
15952d1d418eSSumit Saxena 
15962d1d418eSSumit Saxena 	sc->facts.ioc_num = facts_data->IOCNumber;
15972d1d418eSSumit Saxena         sc->facts.who_init = facts_data->WhoInit;
15982d1d418eSSumit Saxena         sc->facts.max_msix_vectors = facts_data->MaxMSIxVectors;
15992d1d418eSSumit Saxena 	sc->facts.personality = (facts_flags &
16002d1d418eSSumit Saxena 	    MPI3_IOCFACTS_FLAGS_PERSONALITY_MASK);
16012d1d418eSSumit Saxena 	sc->facts.dma_mask = (facts_flags &
16022d1d418eSSumit Saxena 	    MPI3_IOCFACTS_FLAGS_DMA_ADDRESS_WIDTH_MASK) >>
16032d1d418eSSumit Saxena 	    MPI3_IOCFACTS_FLAGS_DMA_ADDRESS_WIDTH_SHIFT;
16042d1d418eSSumit Saxena         sc->facts.protocol_flags = facts_data->ProtocolFlags;
16052d1d418eSSumit Saxena         sc->facts.mpi_version = (facts_data->MPIVersion.Word);
16062d1d418eSSumit Saxena         sc->facts.max_reqs = (facts_data->MaxOutstandingRequests);
16072d1d418eSSumit Saxena         sc->facts.product_id = (facts_data->ProductID);
16082d1d418eSSumit Saxena 	sc->facts.reply_sz = (facts_data->ReplyFrameSize) * 4;
16092d1d418eSSumit Saxena         sc->facts.exceptions = (facts_data->IOCExceptions);
16102d1d418eSSumit Saxena         sc->facts.max_perids = (facts_data->MaxPersistentID);
16112d1d418eSSumit Saxena         sc->facts.max_vds = (facts_data->MaxVDs);
16122d1d418eSSumit Saxena         sc->facts.max_hpds = (facts_data->MaxHostPDs);
16132d1d418eSSumit Saxena         sc->facts.max_advhpds = (facts_data->MaxAdvHostPDs);
16142d1d418eSSumit Saxena         sc->facts.max_raidpds = (facts_data->MaxRAIDPDs);
16152d1d418eSSumit Saxena         sc->facts.max_nvme = (facts_data->MaxNVMe);
16162d1d418eSSumit Saxena         sc->facts.max_pcieswitches =
16172d1d418eSSumit Saxena                 (facts_data->MaxPCIeSwitches);
16182d1d418eSSumit Saxena         sc->facts.max_sasexpanders =
16192d1d418eSSumit Saxena                 (facts_data->MaxSASExpanders);
16202d1d418eSSumit Saxena         sc->facts.max_sasinitiators =
16212d1d418eSSumit Saxena                 (facts_data->MaxSASInitiators);
16222d1d418eSSumit Saxena         sc->facts.max_enclosures = (facts_data->MaxEnclosures);
16232d1d418eSSumit Saxena         sc->facts.min_devhandle = (facts_data->MinDevHandle);
16242d1d418eSSumit Saxena         sc->facts.max_devhandle = (facts_data->MaxDevHandle);
16252d1d418eSSumit Saxena 	sc->facts.max_op_req_q =
16262d1d418eSSumit Saxena                 (facts_data->MaxOperationalRequestQueues);
16272d1d418eSSumit Saxena 	sc->facts.max_op_reply_q =
16282d1d418eSSumit Saxena                 (facts_data->MaxOperationalReplyQueues);
16292d1d418eSSumit Saxena         sc->facts.ioc_capabilities =
16302d1d418eSSumit Saxena                 (facts_data->IOCCapabilities);
16312d1d418eSSumit Saxena         sc->facts.fw_ver.build_num =
16322d1d418eSSumit Saxena                 (facts_data->FWVersion.BuildNum);
16332d1d418eSSumit Saxena         sc->facts.fw_ver.cust_id =
16342d1d418eSSumit Saxena                 (facts_data->FWVersion.CustomerID);
16352d1d418eSSumit Saxena         sc->facts.fw_ver.ph_minor = facts_data->FWVersion.PhaseMinor;
16362d1d418eSSumit Saxena         sc->facts.fw_ver.ph_major = facts_data->FWVersion.PhaseMajor;
16372d1d418eSSumit Saxena         sc->facts.fw_ver.gen_minor = facts_data->FWVersion.GenMinor;
16382d1d418eSSumit Saxena         sc->facts.fw_ver.gen_major = facts_data->FWVersion.GenMajor;
16392d1d418eSSumit Saxena         sc->max_msix_vectors = min(sc->max_msix_vectors,
16402d1d418eSSumit Saxena             sc->facts.max_msix_vectors);
16412d1d418eSSumit Saxena         sc->facts.sge_mod_mask = facts_data->SGEModifierMask;
16422d1d418eSSumit Saxena         sc->facts.sge_mod_value = facts_data->SGEModifierValue;
16432d1d418eSSumit Saxena         sc->facts.sge_mod_shift = facts_data->SGEModifierShift;
16442d1d418eSSumit Saxena         sc->facts.shutdown_timeout =
16452d1d418eSSumit Saxena                 (facts_data->ShutdownTimeout);
16462d1d418eSSumit Saxena 	sc->facts.max_dev_per_tg = facts_data->MaxDevicesPerThrottleGroup;
16472d1d418eSSumit Saxena 	sc->facts.io_throttle_data_length =
16482d1d418eSSumit Saxena 	    facts_data->IOThrottleDataLength;
16492d1d418eSSumit Saxena 	sc->facts.max_io_throttle_group =
16502d1d418eSSumit Saxena 	    facts_data->MaxIOThrottleGroup;
16512d1d418eSSumit Saxena 	sc->facts.io_throttle_low = facts_data->IOThrottleLow;
16522d1d418eSSumit Saxena 	sc->facts.io_throttle_high = facts_data->IOThrottleHigh;
16532d1d418eSSumit Saxena 
16542d1d418eSSumit Saxena 	/*Store in 512b block count*/
16552d1d418eSSumit Saxena 	if (sc->facts.io_throttle_data_length)
16562d1d418eSSumit Saxena 		sc->io_throttle_data_length =
16572d1d418eSSumit Saxena 		    (sc->facts.io_throttle_data_length * 2 * 4);
16582d1d418eSSumit Saxena 	else
16592d1d418eSSumit Saxena 		/* set the length to 1MB + 1K to disable throttle*/
16602d1d418eSSumit Saxena 		sc->io_throttle_data_length = MPI3MR_MAX_SECTORS + 2;
16612d1d418eSSumit Saxena 
16622d1d418eSSumit Saxena 	sc->io_throttle_high = (sc->facts.io_throttle_high * 2 * 1024);
16632d1d418eSSumit Saxena 	sc->io_throttle_low = (sc->facts.io_throttle_low * 2 * 1024);
16642d1d418eSSumit Saxena 
166528a27434SWarner Losh 	fwver = &sc->facts.fw_ver;
166628a27434SWarner Losh 	snprintf(sc->fw_version, sizeof(sc->fw_version),
166728a27434SWarner Losh 	    "%d.%d.%d.%d.%05d-%05d",
166828a27434SWarner Losh 	    fwver->gen_major, fwver->gen_minor, fwver->ph_major,
166928a27434SWarner Losh 	    fwver->ph_minor, fwver->cust_id, fwver->build_num);
167028a27434SWarner Losh 
16712d1d418eSSumit Saxena 	mpi3mr_dprint(sc, MPI3MR_INFO, "ioc_num(%d), maxopQ(%d), maxopRepQ(%d), maxdh(%d),"
16722d1d418eSSumit Saxena             "maxreqs(%d), mindh(%d) maxPDs(%d) maxvectors(%d) maxperids(%d)\n",
16732d1d418eSSumit Saxena 	    sc->facts.ioc_num, sc->facts.max_op_req_q,
16742d1d418eSSumit Saxena 	    sc->facts.max_op_reply_q, sc->facts.max_devhandle,
16752d1d418eSSumit Saxena             sc->facts.max_reqs, sc->facts.min_devhandle,
16762d1d418eSSumit Saxena             sc->facts.max_pds, sc->facts.max_msix_vectors,
16772d1d418eSSumit Saxena             sc->facts.max_perids);
16782d1d418eSSumit Saxena         mpi3mr_dprint(sc, MPI3MR_INFO, "SGEModMask 0x%x SGEModVal 0x%x SGEModShift 0x%x\n",
16792d1d418eSSumit Saxena             sc->facts.sge_mod_mask, sc->facts.sge_mod_value,
16802d1d418eSSumit Saxena             sc->facts.sge_mod_shift);
16812d1d418eSSumit Saxena 	mpi3mr_dprint(sc, MPI3MR_INFO,
16822d1d418eSSumit Saxena 	    "max_dev_per_throttle_group(%d), max_throttle_groups(%d), io_throttle_data_len(%dKiB), io_throttle_high(%dMiB), io_throttle_low(%dMiB)\n",
16832d1d418eSSumit Saxena 	    sc->facts.max_dev_per_tg, sc->facts.max_io_throttle_group,
16842d1d418eSSumit Saxena 	    sc->facts.io_throttle_data_length * 4,
16852d1d418eSSumit Saxena 	    sc->facts.io_throttle_high, sc->facts.io_throttle_low);
16862d1d418eSSumit Saxena 
16872d1d418eSSumit Saxena 	sc->max_host_ios = sc->facts.max_reqs -
16882d1d418eSSumit Saxena 	    (MPI3MR_INTERNALCMDS_RESVD + 1);
16892d1d418eSSumit Saxena 
169091d96135SWarner Losh 	/*
169191d96135SWarner Losh 	 * Set the DMA mask for the card.  dma_mask is the number of bits that
16921ec7c672SWarner Losh 	 * can have bits set in them.  Translate this into bus_dma loaddr args.
16931ec7c672SWarner Losh 	 * Add sanity for more bits than address space or other overflow
169491d96135SWarner Losh 	 * situations.
169591d96135SWarner Losh 	 */
169691d96135SWarner Losh 	if (sc->facts.dma_mask == 0 ||
169791d96135SWarner Losh 	    (sc->facts.dma_mask >= sizeof(bus_addr_t) * 8))
169891d96135SWarner Losh 		sc->dma_loaddr = BUS_SPACE_MAXADDR;
169991d96135SWarner Losh 	else
170091d96135SWarner Losh 		sc->dma_loaddr = ~((1ull << sc->facts.dma_mask) - 1);
170191d96135SWarner Losh 	mpi3mr_dprint(sc, MPI3MR_INFO,
17021ec7c672SWarner Losh 	    "dma_mask bits: %d loaddr 0x%jx\n",
17031ec7c672SWarner Losh 	    sc->facts.dma_mask, sc->dma_loaddr);
170491d96135SWarner Losh 
17052d1d418eSSumit Saxena 	return retval;
17062d1d418eSSumit Saxena }
17072d1d418eSSumit Saxena 
mpi3mr_setup_reply_free_queues(struct mpi3mr_softc * sc)17082d1d418eSSumit Saxena static inline void mpi3mr_setup_reply_free_queues(struct mpi3mr_softc *sc)
17092d1d418eSSumit Saxena {
17102d1d418eSSumit Saxena 	int i;
17112d1d418eSSumit Saxena 	bus_addr_t phys_addr;
17122d1d418eSSumit Saxena 
17132d1d418eSSumit Saxena 	/* initialize Reply buffer Queue */
17142d1d418eSSumit Saxena 	for (i = 0, phys_addr = sc->reply_buf_phys;
17152d1d418eSSumit Saxena 	    i < sc->num_reply_bufs; i++, phys_addr += sc->reply_sz)
17162d1d418eSSumit Saxena 		sc->reply_free_q[i] = phys_addr;
17172d1d418eSSumit Saxena 	sc->reply_free_q[i] = (0);
17182d1d418eSSumit Saxena 
17192d1d418eSSumit Saxena 	/* initialize Sense Buffer Queue */
17202d1d418eSSumit Saxena 	for (i = 0, phys_addr = sc->sense_buf_phys;
17212d1d418eSSumit Saxena 	    i < sc->num_sense_bufs; i++, phys_addr += MPI3MR_SENSEBUF_SZ)
17222d1d418eSSumit Saxena 		sc->sense_buf_q[i] = phys_addr;
17232d1d418eSSumit Saxena 	sc->sense_buf_q[i] = (0);
17242d1d418eSSumit Saxena 
17252d1d418eSSumit Saxena }
17262d1d418eSSumit Saxena 
mpi3mr_reply_dma_alloc(struct mpi3mr_softc * sc)17272d1d418eSSumit Saxena static int mpi3mr_reply_dma_alloc(struct mpi3mr_softc *sc)
17282d1d418eSSumit Saxena {
17292d1d418eSSumit Saxena 	U32 sz;
17302d1d418eSSumit Saxena 
17312d1d418eSSumit Saxena 	sc->num_reply_bufs = sc->facts.max_reqs + MPI3MR_NUM_EVTREPLIES;
17322d1d418eSSumit Saxena 	sc->reply_free_q_sz = sc->num_reply_bufs + 1;
17332d1d418eSSumit Saxena 	sc->num_sense_bufs = sc->facts.max_reqs / MPI3MR_SENSEBUF_FACTOR;
17342d1d418eSSumit Saxena 	sc->sense_buf_q_sz = sc->num_sense_bufs + 1;
17352d1d418eSSumit Saxena 
17362d1d418eSSumit Saxena 	sz = sc->num_reply_bufs * sc->reply_sz;
17372d1d418eSSumit Saxena 
17382d1d418eSSumit Saxena 	if (bus_dma_tag_create(sc->mpi3mr_parent_dmat,  /* parent */
17392d1d418eSSumit Saxena 				16, 0,			/* algnmnt, boundary */
1740ee7c431cSWarner Losh 				sc->dma_loaddr,		/* lowaddr */
17411ec7c672SWarner Losh 				BUS_SPACE_MAXADDR,	/* highaddr */
17422d1d418eSSumit Saxena 				NULL, NULL,		/* filter, filterarg */
17432d1d418eSSumit Saxena                                 sz,			/* maxsize */
17442d1d418eSSumit Saxena                                 1,			/* nsegments */
17452d1d418eSSumit Saxena                                 sz,			/* maxsegsize */
17462d1d418eSSumit Saxena                                 0,			/* flags */
17472d1d418eSSumit Saxena                                 NULL, NULL,		/* lockfunc, lockarg */
17482d1d418eSSumit Saxena                                 &sc->reply_buf_tag)) {
17492d1d418eSSumit Saxena 		mpi3mr_dprint(sc, MPI3MR_ERROR, "Cannot allocate request DMA tag\n");
17502d1d418eSSumit Saxena 		return (ENOMEM);
17512d1d418eSSumit Saxena         }
17522d1d418eSSumit Saxena 
17532d1d418eSSumit Saxena 	if (bus_dmamem_alloc(sc->reply_buf_tag, (void **)&sc->reply_buf,
17542d1d418eSSumit Saxena 	    BUS_DMA_NOWAIT, &sc->reply_buf_dmamap)) {
17552d1d418eSSumit Saxena 		mpi3mr_dprint(sc, MPI3MR_ERROR, "Func: %s line: %d  DMA mem alloc failed\n",
17562d1d418eSSumit Saxena 			__func__, __LINE__);
17572d1d418eSSumit Saxena 		return (ENOMEM);
17582d1d418eSSumit Saxena         }
17592d1d418eSSumit Saxena 
17602d1d418eSSumit Saxena 	bzero(sc->reply_buf, sz);
17612d1d418eSSumit Saxena         bus_dmamap_load(sc->reply_buf_tag, sc->reply_buf_dmamap, sc->reply_buf, sz,
176239a3e6a8SAlexander Motin 	    mpi3mr_memaddr_cb, &sc->reply_buf_phys, BUS_DMA_NOWAIT);
17632d1d418eSSumit Saxena 
17642d1d418eSSumit Saxena 	sc->reply_buf_dma_min_address = sc->reply_buf_phys;
17652d1d418eSSumit Saxena 	sc->reply_buf_dma_max_address = sc->reply_buf_phys + sz;
17662d1d418eSSumit Saxena 	mpi3mr_dprint(sc, MPI3MR_XINFO, "reply buf (0x%p): depth(%d), frame_size(%d), "
17672d1d418eSSumit Saxena 	    "pool_size(%d kB), reply_buf_dma(0x%llx)\n",
17682d1d418eSSumit Saxena 	    sc->reply_buf, sc->num_reply_bufs, sc->reply_sz,
17692d1d418eSSumit Saxena 	    (sz / 1024), (unsigned long long)sc->reply_buf_phys);
17702d1d418eSSumit Saxena 
17712d1d418eSSumit Saxena 	/* reply free queue, 8 byte align */
17722d1d418eSSumit Saxena 	sz = sc->reply_free_q_sz * 8;
17732d1d418eSSumit Saxena 
17742d1d418eSSumit Saxena         if (bus_dma_tag_create(sc->mpi3mr_parent_dmat,    /* parent */
17752d1d418eSSumit Saxena 				8, 0,			/* algnmnt, boundary */
1776ee7c431cSWarner Losh 				sc->dma_loaddr,		/* lowaddr */
17771ec7c672SWarner Losh 				BUS_SPACE_MAXADDR,	/* highaddr */
17782d1d418eSSumit Saxena 				NULL, NULL,		/* filter, filterarg */
17792d1d418eSSumit Saxena                                 sz,			/* maxsize */
17802d1d418eSSumit Saxena                                 1,			/* nsegments */
17812d1d418eSSumit Saxena                                 sz,			/* maxsegsize */
17822d1d418eSSumit Saxena                                 0,			/* flags */
17832d1d418eSSumit Saxena                                 NULL, NULL,		/* lockfunc, lockarg */
17842d1d418eSSumit Saxena                                 &sc->reply_free_q_tag)) {
17852d1d418eSSumit Saxena 		mpi3mr_dprint(sc, MPI3MR_ERROR, "Cannot allocate reply free queue DMA tag\n");
17862d1d418eSSumit Saxena 		return (ENOMEM);
17872d1d418eSSumit Saxena         }
17882d1d418eSSumit Saxena 
17892d1d418eSSumit Saxena         if (bus_dmamem_alloc(sc->reply_free_q_tag, (void **)&sc->reply_free_q,
17902d1d418eSSumit Saxena 	    BUS_DMA_NOWAIT, &sc->reply_free_q_dmamap)) {
17912d1d418eSSumit Saxena 		mpi3mr_dprint(sc, MPI3MR_ERROR, "Func: %s line: %d  DMA mem alloc failed\n",
17922d1d418eSSumit Saxena 			__func__, __LINE__);
17932d1d418eSSumit Saxena 		return (ENOMEM);
17942d1d418eSSumit Saxena         }
17952d1d418eSSumit Saxena 
17962d1d418eSSumit Saxena 	bzero(sc->reply_free_q, sz);
17972d1d418eSSumit Saxena         bus_dmamap_load(sc->reply_free_q_tag, sc->reply_free_q_dmamap, sc->reply_free_q, sz,
179839a3e6a8SAlexander Motin 	    mpi3mr_memaddr_cb, &sc->reply_free_q_phys, BUS_DMA_NOWAIT);
17992d1d418eSSumit Saxena 
18002d1d418eSSumit Saxena 	mpi3mr_dprint(sc, MPI3MR_XINFO, "reply_free_q (0x%p): depth(%d), frame_size(%d), "
18012d1d418eSSumit Saxena 	    "pool_size(%d kB), reply_free_q_dma(0x%llx)\n",
18022d1d418eSSumit Saxena 	    sc->reply_free_q, sc->reply_free_q_sz, 8, (sz / 1024),
18032d1d418eSSumit Saxena 	    (unsigned long long)sc->reply_free_q_phys);
18042d1d418eSSumit Saxena 
18052d1d418eSSumit Saxena 	/* sense buffer pool,  4 byte align */
18062d1d418eSSumit Saxena 	sz = sc->num_sense_bufs * MPI3MR_SENSEBUF_SZ;
18072d1d418eSSumit Saxena 
18082d1d418eSSumit Saxena         if (bus_dma_tag_create(sc->mpi3mr_parent_dmat,    /* parent */
18092d1d418eSSumit Saxena 				4, 0,			/* algnmnt, boundary */
1810ee7c431cSWarner Losh 				sc->dma_loaddr,		/* lowaddr */
18111ec7c672SWarner Losh 				BUS_SPACE_MAXADDR,	/* highaddr */
18122d1d418eSSumit Saxena 				NULL, NULL,		/* filter, filterarg */
18132d1d418eSSumit Saxena                                 sz,			/* maxsize */
18142d1d418eSSumit Saxena                                 1,			/* nsegments */
18152d1d418eSSumit Saxena                                 sz,			/* maxsegsize */
18162d1d418eSSumit Saxena                                 0,			/* flags */
18172d1d418eSSumit Saxena                                 NULL, NULL,		/* lockfunc, lockarg */
18182d1d418eSSumit Saxena                                 &sc->sense_buf_tag)) {
18192d1d418eSSumit Saxena 		mpi3mr_dprint(sc, MPI3MR_ERROR, "Cannot allocate Sense buffer DMA tag\n");
18202d1d418eSSumit Saxena 		return (ENOMEM);
18212d1d418eSSumit Saxena         }
18222d1d418eSSumit Saxena 
18232d1d418eSSumit Saxena 	if (bus_dmamem_alloc(sc->sense_buf_tag, (void **)&sc->sense_buf,
18242d1d418eSSumit Saxena 	    BUS_DMA_NOWAIT, &sc->sense_buf_dmamap)) {
18252d1d418eSSumit Saxena 		mpi3mr_dprint(sc, MPI3MR_ERROR, "Func: %s line: %d  DMA mem alloc failed\n",
18262d1d418eSSumit Saxena 			__func__, __LINE__);
18272d1d418eSSumit Saxena 		return (ENOMEM);
18282d1d418eSSumit Saxena         }
18292d1d418eSSumit Saxena 
18302d1d418eSSumit Saxena 	bzero(sc->sense_buf, sz);
18312d1d418eSSumit Saxena         bus_dmamap_load(sc->sense_buf_tag, sc->sense_buf_dmamap, sc->sense_buf, sz,
183239a3e6a8SAlexander Motin 	    mpi3mr_memaddr_cb, &sc->sense_buf_phys, BUS_DMA_NOWAIT);
18332d1d418eSSumit Saxena 
18342d1d418eSSumit Saxena 	mpi3mr_dprint(sc, MPI3MR_XINFO, "sense_buf (0x%p): depth(%d), frame_size(%d), "
18352d1d418eSSumit Saxena 	    "pool_size(%d kB), sense_dma(0x%llx)\n",
18362d1d418eSSumit Saxena 	    sc->sense_buf, sc->num_sense_bufs, MPI3MR_SENSEBUF_SZ,
18372d1d418eSSumit Saxena 	    (sz / 1024), (unsigned long long)sc->sense_buf_phys);
18382d1d418eSSumit Saxena 
18392d1d418eSSumit Saxena 	/* sense buffer queue, 8 byte align */
18402d1d418eSSumit Saxena 	sz = sc->sense_buf_q_sz * 8;
18412d1d418eSSumit Saxena 
18422d1d418eSSumit Saxena         if (bus_dma_tag_create(sc->mpi3mr_parent_dmat,    /* parent */
18432d1d418eSSumit Saxena 				8, 0,			/* algnmnt, boundary */
1844ee7c431cSWarner Losh 				sc->dma_loaddr,		/* lowaddr */
18451ec7c672SWarner Losh 				BUS_SPACE_MAXADDR,	/* highaddr */
18462d1d418eSSumit Saxena 				NULL, NULL,		/* filter, filterarg */
18472d1d418eSSumit Saxena                                 sz,			/* maxsize */
18482d1d418eSSumit Saxena                                 1,			/* nsegments */
18492d1d418eSSumit Saxena                                 sz,			/* maxsegsize */
18502d1d418eSSumit Saxena                                 0,			/* flags */
18512d1d418eSSumit Saxena                                 NULL, NULL,		/* lockfunc, lockarg */
18522d1d418eSSumit Saxena                                 &sc->sense_buf_q_tag)) {
18532d1d418eSSumit Saxena 		mpi3mr_dprint(sc, MPI3MR_ERROR, "Cannot allocate Sense buffer Queue DMA tag\n");
18542d1d418eSSumit Saxena 		return (ENOMEM);
18552d1d418eSSumit Saxena         }
18562d1d418eSSumit Saxena 
18572d1d418eSSumit Saxena 	if (bus_dmamem_alloc(sc->sense_buf_q_tag, (void **)&sc->sense_buf_q,
18582d1d418eSSumit Saxena 	    BUS_DMA_NOWAIT, &sc->sense_buf_q_dmamap)) {
18592d1d418eSSumit Saxena 		mpi3mr_dprint(sc, MPI3MR_ERROR, "Func: %s line: %d  DMA mem alloc failed\n",
18602d1d418eSSumit Saxena 			__func__, __LINE__);
18612d1d418eSSumit Saxena 		return (ENOMEM);
18622d1d418eSSumit Saxena         }
18632d1d418eSSumit Saxena 
18642d1d418eSSumit Saxena 	bzero(sc->sense_buf_q, sz);
18652d1d418eSSumit Saxena         bus_dmamap_load(sc->sense_buf_q_tag, sc->sense_buf_q_dmamap, sc->sense_buf_q, sz,
186639a3e6a8SAlexander Motin 	    mpi3mr_memaddr_cb, &sc->sense_buf_q_phys, BUS_DMA_NOWAIT);
18672d1d418eSSumit Saxena 
18682d1d418eSSumit Saxena 	mpi3mr_dprint(sc, MPI3MR_XINFO, "sense_buf_q (0x%p): depth(%d), frame_size(%d), "
18692d1d418eSSumit Saxena 	    "pool_size(%d kB), sense_dma(0x%llx)\n",
18702d1d418eSSumit Saxena 	    sc->sense_buf_q, sc->sense_buf_q_sz, 8, (sz / 1024),
18712d1d418eSSumit Saxena 	    (unsigned long long)sc->sense_buf_q_phys);
18722d1d418eSSumit Saxena 
18732d1d418eSSumit Saxena 	return 0;
18742d1d418eSSumit Saxena }
18752d1d418eSSumit Saxena 
mpi3mr_reply_alloc(struct mpi3mr_softc * sc)18762d1d418eSSumit Saxena static int mpi3mr_reply_alloc(struct mpi3mr_softc *sc)
18772d1d418eSSumit Saxena {
18782d1d418eSSumit Saxena 	int retval = 0;
18792d1d418eSSumit Saxena 	U32 i;
18802d1d418eSSumit Saxena 
18812d1d418eSSumit Saxena 	if (sc->init_cmds.reply)
18822d1d418eSSumit Saxena 		goto post_reply_sbuf;
18832d1d418eSSumit Saxena 
18842d1d418eSSumit Saxena 	sc->init_cmds.reply = malloc(sc->reply_sz,
18852d1d418eSSumit Saxena 		M_MPI3MR, M_NOWAIT | M_ZERO);
18862d1d418eSSumit Saxena 
18872d1d418eSSumit Saxena 	if (!sc->init_cmds.reply) {
18882d1d418eSSumit Saxena 		printf(IOCNAME "Cannot allocate memory for init_cmds.reply\n",
18892d1d418eSSumit Saxena 		    sc->name);
18902d1d418eSSumit Saxena 		goto out_failed;
18912d1d418eSSumit Saxena 	}
18922d1d418eSSumit Saxena 
18932d1d418eSSumit Saxena 	sc->ioctl_cmds.reply = malloc(sc->reply_sz, M_MPI3MR, M_NOWAIT | M_ZERO);
18942d1d418eSSumit Saxena 	if (!sc->ioctl_cmds.reply) {
18952d1d418eSSumit Saxena 		printf(IOCNAME "Cannot allocate memory for ioctl_cmds.reply\n",
18962d1d418eSSumit Saxena 		    sc->name);
18972d1d418eSSumit Saxena 		goto out_failed;
18982d1d418eSSumit Saxena 	}
18992d1d418eSSumit Saxena 
19002d1d418eSSumit Saxena 	sc->host_tm_cmds.reply = malloc(sc->reply_sz, M_MPI3MR, M_NOWAIT | M_ZERO);
19012d1d418eSSumit Saxena 	if (!sc->host_tm_cmds.reply) {
19022d1d418eSSumit Saxena 		printf(IOCNAME "Cannot allocate memory for host_tm.reply\n",
19032d1d418eSSumit Saxena 		    sc->name);
19042d1d418eSSumit Saxena 		goto out_failed;
19052d1d418eSSumit Saxena 	}
19062d1d418eSSumit Saxena 	for (i=0; i<MPI3MR_NUM_DEVRMCMD; i++) {
19072d1d418eSSumit Saxena 		sc->dev_rmhs_cmds[i].reply = malloc(sc->reply_sz,
19082d1d418eSSumit Saxena 		    M_MPI3MR, M_NOWAIT | M_ZERO);
19092d1d418eSSumit Saxena 		if (!sc->dev_rmhs_cmds[i].reply) {
19102d1d418eSSumit Saxena 			printf(IOCNAME "Cannot allocate memory for"
19112d1d418eSSumit Saxena 			    " dev_rmhs_cmd[%d].reply\n",
19122d1d418eSSumit Saxena 			    sc->name, i);
19132d1d418eSSumit Saxena 			goto out_failed;
19142d1d418eSSumit Saxena 		}
19152d1d418eSSumit Saxena 	}
19162d1d418eSSumit Saxena 
19172d1d418eSSumit Saxena 	for (i = 0; i < MPI3MR_NUM_EVTACKCMD; i++) {
19182d1d418eSSumit Saxena 		sc->evtack_cmds[i].reply = malloc(sc->reply_sz,
19192d1d418eSSumit Saxena 			M_MPI3MR, M_NOWAIT | M_ZERO);
19202d1d418eSSumit Saxena 		if (!sc->evtack_cmds[i].reply)
19212d1d418eSSumit Saxena 			goto out_failed;
19222d1d418eSSumit Saxena 	}
19232d1d418eSSumit Saxena 
19242d1d418eSSumit Saxena 	sc->dev_handle_bitmap_sz = MPI3MR_DIV_ROUND_UP(sc->facts.max_devhandle, 8);
19252d1d418eSSumit Saxena 
19262d1d418eSSumit Saxena 	sc->removepend_bitmap = malloc(sc->dev_handle_bitmap_sz,
19272d1d418eSSumit Saxena 	    M_MPI3MR, M_NOWAIT | M_ZERO);
19282d1d418eSSumit Saxena 	if (!sc->removepend_bitmap) {
19292d1d418eSSumit Saxena 		printf(IOCNAME "Cannot alloc memory for remove pend bitmap\n",
19302d1d418eSSumit Saxena 		    sc->name);
19312d1d418eSSumit Saxena 		goto out_failed;
19322d1d418eSSumit Saxena 	}
19332d1d418eSSumit Saxena 
19342d1d418eSSumit Saxena 	sc->devrem_bitmap_sz = MPI3MR_DIV_ROUND_UP(MPI3MR_NUM_DEVRMCMD, 8);
19352d1d418eSSumit Saxena 	sc->devrem_bitmap = malloc(sc->devrem_bitmap_sz,
19362d1d418eSSumit Saxena 	    M_MPI3MR, M_NOWAIT | M_ZERO);
19372d1d418eSSumit Saxena 	if (!sc->devrem_bitmap) {
19382d1d418eSSumit Saxena 		printf(IOCNAME "Cannot alloc memory for dev remove bitmap\n",
19392d1d418eSSumit Saxena 		    sc->name);
19402d1d418eSSumit Saxena 		goto out_failed;
19412d1d418eSSumit Saxena 	}
19422d1d418eSSumit Saxena 
19432d1d418eSSumit Saxena 	sc->evtack_cmds_bitmap_sz = MPI3MR_DIV_ROUND_UP(MPI3MR_NUM_EVTACKCMD, 8);
19442d1d418eSSumit Saxena 
19452d1d418eSSumit Saxena 	sc->evtack_cmds_bitmap = malloc(sc->evtack_cmds_bitmap_sz,
19462d1d418eSSumit Saxena 		M_MPI3MR, M_NOWAIT | M_ZERO);
19472d1d418eSSumit Saxena 	if (!sc->evtack_cmds_bitmap)
19482d1d418eSSumit Saxena 		goto out_failed;
19492d1d418eSSumit Saxena 
19502d1d418eSSumit Saxena 	if (mpi3mr_reply_dma_alloc(sc)) {
19512d1d418eSSumit Saxena 		printf(IOCNAME "func:%s line:%d DMA memory allocation failed\n",
19522d1d418eSSumit Saxena 		    sc->name, __func__, __LINE__);
19532d1d418eSSumit Saxena 		goto out_failed;
19542d1d418eSSumit Saxena 	}
19552d1d418eSSumit Saxena 
19562d1d418eSSumit Saxena post_reply_sbuf:
19572d1d418eSSumit Saxena 	mpi3mr_setup_reply_free_queues(sc);
19582d1d418eSSumit Saxena 	return retval;
19592d1d418eSSumit Saxena out_failed:
19602d1d418eSSumit Saxena 	mpi3mr_cleanup_interrupts(sc);
19612d1d418eSSumit Saxena 	mpi3mr_free_mem(sc);
19622d1d418eSSumit Saxena 	retval = -1;
19632d1d418eSSumit Saxena 	return retval;
19642d1d418eSSumit Saxena }
19652d1d418eSSumit Saxena 
19662d1d418eSSumit Saxena static void
mpi3mr_print_fw_pkg_ver(struct mpi3mr_softc * sc)19672d1d418eSSumit Saxena mpi3mr_print_fw_pkg_ver(struct mpi3mr_softc *sc)
19682d1d418eSSumit Saxena {
19692d1d418eSSumit Saxena 	int retval = 0;
19702d1d418eSSumit Saxena 	void *fw_pkg_ver = NULL;
19712d1d418eSSumit Saxena 	bus_dma_tag_t fw_pkg_ver_tag;
19722d1d418eSSumit Saxena 	bus_dmamap_t fw_pkg_ver_map;
19732d1d418eSSumit Saxena 	bus_addr_t fw_pkg_ver_dma;
19742d1d418eSSumit Saxena 	Mpi3CIUploadRequest_t ci_upload;
19752d1d418eSSumit Saxena 	Mpi3ComponentImageHeader_t *ci_header;
19762d1d418eSSumit Saxena 	U32 fw_pkg_ver_len = sizeof(*ci_header);
19772d1d418eSSumit Saxena 	U8 sgl_flags = MPI3MR_SGEFLAGS_SYSTEM_SIMPLE_END_OF_LIST;
19782d1d418eSSumit Saxena 
19792d1d418eSSumit Saxena 	if (bus_dma_tag_create(sc->mpi3mr_parent_dmat,  /* parent */
19802d1d418eSSumit Saxena 				4, 0,			/* algnmnt, boundary */
1981ee7c431cSWarner Losh 				sc->dma_loaddr,		/* lowaddr */
19821ec7c672SWarner Losh 				BUS_SPACE_MAXADDR,	/* highaddr */
19832d1d418eSSumit Saxena 				NULL, NULL,		/* filter, filterarg */
19842d1d418eSSumit Saxena 				fw_pkg_ver_len,		/* maxsize */
19852d1d418eSSumit Saxena 				1,			/* nsegments */
19862d1d418eSSumit Saxena 				fw_pkg_ver_len,		/* maxsegsize */
19872d1d418eSSumit Saxena 				0,			/* flags */
19882d1d418eSSumit Saxena 				NULL, NULL,		/* lockfunc, lockarg */
19892d1d418eSSumit Saxena 				&fw_pkg_ver_tag)) {
19902d1d418eSSumit Saxena 		mpi3mr_dprint(sc, MPI3MR_ERROR, "Cannot allocate fw package version request DMA tag\n");
19912d1d418eSSumit Saxena 		return;
19922d1d418eSSumit Saxena 	}
19932d1d418eSSumit Saxena 
19942d1d418eSSumit Saxena 	if (bus_dmamem_alloc(fw_pkg_ver_tag, (void **)&fw_pkg_ver, BUS_DMA_NOWAIT, &fw_pkg_ver_map)) {
19952d1d418eSSumit Saxena 		mpi3mr_dprint(sc, MPI3MR_ERROR, "Func: %s line: %d fw package version DMA mem alloc failed\n",
19962d1d418eSSumit Saxena 			      __func__, __LINE__);
19972d1d418eSSumit Saxena 		return;
19982d1d418eSSumit Saxena 	}
19992d1d418eSSumit Saxena 
20002d1d418eSSumit Saxena 	bzero(fw_pkg_ver, fw_pkg_ver_len);
20012d1d418eSSumit Saxena 
200239a3e6a8SAlexander Motin 	bus_dmamap_load(fw_pkg_ver_tag, fw_pkg_ver_map, fw_pkg_ver, fw_pkg_ver_len,
200339a3e6a8SAlexander Motin 	    mpi3mr_memaddr_cb, &fw_pkg_ver_dma, BUS_DMA_NOWAIT);
20042d1d418eSSumit Saxena 
20052d1d418eSSumit Saxena 	mpi3mr_dprint(sc, MPI3MR_XINFO, "Func: %s line: %d fw package version phys addr= %#016jx size= %d\n",
20062d1d418eSSumit Saxena 		      __func__, __LINE__, (uintmax_t)fw_pkg_ver_dma, fw_pkg_ver_len);
20072d1d418eSSumit Saxena 
20082d1d418eSSumit Saxena 	if (!fw_pkg_ver) {
20092d1d418eSSumit Saxena 		mpi3mr_dprint(sc, MPI3MR_ERROR, "Memory alloc for fw package version failed\n");
20102d1d418eSSumit Saxena 		goto out;
20112d1d418eSSumit Saxena 	}
20122d1d418eSSumit Saxena 
20132d1d418eSSumit Saxena 	memset(&ci_upload, 0, sizeof(ci_upload));
20142d1d418eSSumit Saxena 	mtx_lock(&sc->init_cmds.completion.lock);
20152d1d418eSSumit Saxena 	if (sc->init_cmds.state & MPI3MR_CMD_PENDING) {
20162d1d418eSSumit Saxena 		mpi3mr_dprint(sc, MPI3MR_INFO,"Issue CI Header Upload: command is in use\n");
20172d1d418eSSumit Saxena 		mtx_unlock(&sc->init_cmds.completion.lock);
20182d1d418eSSumit Saxena 		goto out;
20192d1d418eSSumit Saxena 	}
20202d1d418eSSumit Saxena 	sc->init_cmds.state = MPI3MR_CMD_PENDING;
20212d1d418eSSumit Saxena 	sc->init_cmds.is_waiting = 1;
20222d1d418eSSumit Saxena 	sc->init_cmds.callback = NULL;
20232d1d418eSSumit Saxena 	ci_upload.HostTag = htole16(MPI3MR_HOSTTAG_INITCMDS);
20242d1d418eSSumit Saxena 	ci_upload.Function = MPI3_FUNCTION_CI_UPLOAD;
20252d1d418eSSumit Saxena 	ci_upload.MsgFlags = MPI3_CI_UPLOAD_MSGFLAGS_LOCATION_PRIMARY;
20262d1d418eSSumit Saxena 	ci_upload.ImageOffset = MPI3_IMAGE_HEADER_SIGNATURE0_OFFSET;
20272d1d418eSSumit Saxena 	ci_upload.SegmentSize = MPI3_IMAGE_HEADER_SIZE;
20282d1d418eSSumit Saxena 
20292d1d418eSSumit Saxena 	mpi3mr_add_sg_single(&ci_upload.SGL, sgl_flags, fw_pkg_ver_len,
20302d1d418eSSumit Saxena 	    fw_pkg_ver_dma);
20312d1d418eSSumit Saxena 
20322d1d418eSSumit Saxena 	init_completion(&sc->init_cmds.completion);
20332d1d418eSSumit Saxena 	if ((retval = mpi3mr_submit_admin_cmd(sc, &ci_upload, sizeof(ci_upload)))) {
20342d1d418eSSumit Saxena 		mpi3mr_dprint(sc, MPI3MR_ERROR, "Issue CI Header Upload: Admin Post failed\n");
20352d1d418eSSumit Saxena 		goto out_unlock;
20362d1d418eSSumit Saxena 	}
20372d1d418eSSumit Saxena 	wait_for_completion_timeout(&sc->init_cmds.completion,
20382d1d418eSSumit Saxena 		(MPI3MR_INTADMCMD_TIMEOUT));
20392d1d418eSSumit Saxena 	if (!(sc->init_cmds.state & MPI3MR_CMD_COMPLETE)) {
20402d1d418eSSumit Saxena 		mpi3mr_dprint(sc, MPI3MR_ERROR, "Issue CI Header Upload: command timed out\n");
20412d1d418eSSumit Saxena 		sc->init_cmds.is_waiting = 0;
20422d1d418eSSumit Saxena 		if (!(sc->init_cmds.state & MPI3MR_CMD_RESET))
20432d1d418eSSumit Saxena 			mpi3mr_check_rh_fault_ioc(sc,
20442d1d418eSSumit Saxena 				MPI3MR_RESET_FROM_GETPKGVER_TIMEOUT);
20452d1d418eSSumit Saxena 		goto out_unlock;
20462d1d418eSSumit Saxena 	}
20472d1d418eSSumit Saxena 	if ((GET_IOC_STATUS(sc->init_cmds.ioc_status)) != MPI3_IOCSTATUS_SUCCESS) {
20482d1d418eSSumit Saxena 		mpi3mr_dprint(sc, MPI3MR_ERROR,
20492d1d418eSSumit Saxena 			      "Issue CI Header Upload: Failed IOCStatus(0x%04x) Loginfo(0x%08x)\n",
20502d1d418eSSumit Saxena 			      GET_IOC_STATUS(sc->init_cmds.ioc_status), sc->init_cmds.ioc_loginfo);
20512d1d418eSSumit Saxena 		goto out_unlock;
20522d1d418eSSumit Saxena 	}
20532d1d418eSSumit Saxena 
20542d1d418eSSumit Saxena 	ci_header = (Mpi3ComponentImageHeader_t *) fw_pkg_ver;
20552d1d418eSSumit Saxena 	mpi3mr_dprint(sc, MPI3MR_XINFO,
20562d1d418eSSumit Saxena 		      "Issue CI Header Upload:EnvVariableOffset(0x%x) \
20572d1d418eSSumit Saxena 		      HeaderSize(0x%x) Signature1(0x%x)\n",
20582d1d418eSSumit Saxena 		      ci_header->EnvironmentVariableOffset,
20592d1d418eSSumit Saxena 		      ci_header->HeaderSize,
20602d1d418eSSumit Saxena 		      ci_header->Signature1);
20612d1d418eSSumit Saxena 	mpi3mr_dprint(sc, MPI3MR_INFO, "FW Package Version: %02d.%02d.%02d.%02d\n",
20622d1d418eSSumit Saxena 		      ci_header->ComponentImageVersion.GenMajor,
20632d1d418eSSumit Saxena 		      ci_header->ComponentImageVersion.GenMinor,
20642d1d418eSSumit Saxena 		      ci_header->ComponentImageVersion.PhaseMajor,
20652d1d418eSSumit Saxena 		      ci_header->ComponentImageVersion.PhaseMinor);
20662d1d418eSSumit Saxena out_unlock:
20672d1d418eSSumit Saxena 	sc->init_cmds.state = MPI3MR_CMD_NOTUSED;
20682d1d418eSSumit Saxena 	mtx_unlock(&sc->init_cmds.completion.lock);
20692d1d418eSSumit Saxena 
20702d1d418eSSumit Saxena out:
20712d1d418eSSumit Saxena 	if (fw_pkg_ver_dma != 0)
20722d1d418eSSumit Saxena 		bus_dmamap_unload(fw_pkg_ver_tag, fw_pkg_ver_map);
20732d1d418eSSumit Saxena 	if (fw_pkg_ver)
20742d1d418eSSumit Saxena 		bus_dmamem_free(fw_pkg_ver_tag, fw_pkg_ver, fw_pkg_ver_map);
20752d1d418eSSumit Saxena 	if (fw_pkg_ver_tag)
20762d1d418eSSumit Saxena 		bus_dma_tag_destroy(fw_pkg_ver_tag);
20772d1d418eSSumit Saxena 
20782d1d418eSSumit Saxena }
20792d1d418eSSumit Saxena 
20802d1d418eSSumit Saxena /**
20812d1d418eSSumit Saxena  * mpi3mr_issue_iocinit - Send IOC Init
20822d1d418eSSumit Saxena  * @sc: Adapter instance reference
20832d1d418eSSumit Saxena  *
20842d1d418eSSumit Saxena  * Issue IOC Init MPI request through admin queue and wait for
20852d1d418eSSumit Saxena  * the completion of it or time out.
20862d1d418eSSumit Saxena  *
20872d1d418eSSumit Saxena  * Return: 0 on success, non-zero on failures.
20882d1d418eSSumit Saxena  */
mpi3mr_issue_iocinit(struct mpi3mr_softc * sc)20892d1d418eSSumit Saxena static int mpi3mr_issue_iocinit(struct mpi3mr_softc *sc)
20902d1d418eSSumit Saxena {
20912d1d418eSSumit Saxena 	Mpi3IOCInitRequest_t iocinit_req;
20922d1d418eSSumit Saxena 	Mpi3DriverInfoLayout_t *drvr_info = NULL;
20932d1d418eSSumit Saxena 	bus_dma_tag_t drvr_info_tag;
20942d1d418eSSumit Saxena 	bus_dmamap_t drvr_info_map;
20952d1d418eSSumit Saxena 	bus_addr_t drvr_info_phys;
20962d1d418eSSumit Saxena 	U32 drvr_info_len = sizeof(*drvr_info);
20972d1d418eSSumit Saxena 	int retval = 0;
20982d1d418eSSumit Saxena 	struct timeval now;
20992d1d418eSSumit Saxena 	uint64_t time_in_msec;
21002d1d418eSSumit Saxena 
21012d1d418eSSumit Saxena 	if (bus_dma_tag_create(sc->mpi3mr_parent_dmat,  /* parent */
21022d1d418eSSumit Saxena 				4, 0,			/* algnmnt, boundary */
2103ee7c431cSWarner Losh 				sc->dma_loaddr,		/* lowaddr */
21041ec7c672SWarner Losh 				BUS_SPACE_MAXADDR,	/* highaddr */
21052d1d418eSSumit Saxena 				NULL, NULL,		/* filter, filterarg */
21062d1d418eSSumit Saxena                                 drvr_info_len,		/* maxsize */
21072d1d418eSSumit Saxena                                 1,			/* nsegments */
21082d1d418eSSumit Saxena                                 drvr_info_len,		/* maxsegsize */
21092d1d418eSSumit Saxena                                 0,			/* flags */
21102d1d418eSSumit Saxena                                 NULL, NULL,		/* lockfunc, lockarg */
21112d1d418eSSumit Saxena                                 &drvr_info_tag)) {
21122d1d418eSSumit Saxena 		mpi3mr_dprint(sc, MPI3MR_ERROR, "Cannot allocate request DMA tag\n");
21132d1d418eSSumit Saxena 		return (ENOMEM);
21142d1d418eSSumit Saxena         }
21152d1d418eSSumit Saxena 
21162d1d418eSSumit Saxena 	if (bus_dmamem_alloc(drvr_info_tag, (void **)&drvr_info,
21172d1d418eSSumit Saxena 	    BUS_DMA_NOWAIT, &drvr_info_map)) {
21182d1d418eSSumit Saxena 		mpi3mr_dprint(sc, MPI3MR_ERROR, "Func: %s line: %d Data  DMA mem alloc failed\n",
21192d1d418eSSumit Saxena 			__func__, __LINE__);
21202d1d418eSSumit Saxena 		return (ENOMEM);
21212d1d418eSSumit Saxena         }
21222d1d418eSSumit Saxena 
21232d1d418eSSumit Saxena 	bzero(drvr_info, drvr_info_len);
21242d1d418eSSumit Saxena         bus_dmamap_load(drvr_info_tag, drvr_info_map, drvr_info, drvr_info_len,
212539a3e6a8SAlexander Motin 	    mpi3mr_memaddr_cb, &drvr_info_phys, BUS_DMA_NOWAIT);
21262d1d418eSSumit Saxena 	mpi3mr_dprint(sc, MPI3MR_XINFO, "Func: %s line: %d IOCfacts drvr_info phys addr= %#016jx size= %d\n",
21272d1d418eSSumit Saxena 	    __func__, __LINE__, (uintmax_t)drvr_info_phys, drvr_info_len);
21282d1d418eSSumit Saxena 
21292d1d418eSSumit Saxena 	if (!drvr_info)
21302d1d418eSSumit Saxena 	{
21312d1d418eSSumit Saxena 		retval = -1;
21322d1d418eSSumit Saxena 		printf(IOCNAME "Memory alloc for Driver Info failed\n",
21332d1d418eSSumit Saxena 		    sc->name);
21342d1d418eSSumit Saxena 		goto out;
21352d1d418eSSumit Saxena 	}
21362d1d418eSSumit Saxena 	drvr_info->InformationLength = (drvr_info_len);
21372d1d418eSSumit Saxena 	strcpy(drvr_info->DriverSignature, "Broadcom");
21382d1d418eSSumit Saxena 	strcpy(drvr_info->OsName, "FreeBSD");
21392d1d418eSSumit Saxena 	strcpy(drvr_info->OsVersion, fmt_os_ver);
21402d1d418eSSumit Saxena 	strcpy(drvr_info->DriverName, MPI3MR_DRIVER_NAME);
21412d1d418eSSumit Saxena 	strcpy(drvr_info->DriverVersion, MPI3MR_DRIVER_VERSION);
21422d1d418eSSumit Saxena 	strcpy(drvr_info->DriverReleaseDate, MPI3MR_DRIVER_RELDATE);
21432d1d418eSSumit Saxena 	drvr_info->DriverCapabilities = 0;
21442d1d418eSSumit Saxena 	memcpy((U8 *)&sc->driver_info, (U8 *)drvr_info, sizeof(sc->driver_info));
21452d1d418eSSumit Saxena 
21462d1d418eSSumit Saxena 	memset(&iocinit_req, 0, sizeof(iocinit_req));
21472d1d418eSSumit Saxena 	mtx_lock(&sc->init_cmds.completion.lock);
21482d1d418eSSumit Saxena 	if (sc->init_cmds.state & MPI3MR_CMD_PENDING) {
21492d1d418eSSumit Saxena 		retval = -1;
21502d1d418eSSumit Saxena 		printf(IOCNAME "Issue IOCInit: Init command is in use\n",
21512d1d418eSSumit Saxena 		    sc->name);
21522d1d418eSSumit Saxena 		mtx_unlock(&sc->init_cmds.completion.lock);
21532d1d418eSSumit Saxena 		goto out;
21542d1d418eSSumit Saxena 	}
21552d1d418eSSumit Saxena 	sc->init_cmds.state = MPI3MR_CMD_PENDING;
21562d1d418eSSumit Saxena 	sc->init_cmds.is_waiting = 1;
21572d1d418eSSumit Saxena 	sc->init_cmds.callback = NULL;
21582d1d418eSSumit Saxena         iocinit_req.HostTag = MPI3MR_HOSTTAG_INITCMDS;
21592d1d418eSSumit Saxena         iocinit_req.Function = MPI3_FUNCTION_IOC_INIT;
21602d1d418eSSumit Saxena         iocinit_req.MPIVersion.Struct.Dev = MPI3_VERSION_DEV;
21612d1d418eSSumit Saxena         iocinit_req.MPIVersion.Struct.Unit = MPI3_VERSION_UNIT;
21622d1d418eSSumit Saxena         iocinit_req.MPIVersion.Struct.Major = MPI3_VERSION_MAJOR;
21632d1d418eSSumit Saxena         iocinit_req.MPIVersion.Struct.Minor = MPI3_VERSION_MINOR;
21642d1d418eSSumit Saxena         iocinit_req.WhoInit = MPI3_WHOINIT_HOST_DRIVER;
21652d1d418eSSumit Saxena         iocinit_req.ReplyFreeQueueDepth = sc->reply_free_q_sz;
21662d1d418eSSumit Saxena         iocinit_req.ReplyFreeQueueAddress =
21672d1d418eSSumit Saxena                 sc->reply_free_q_phys;
21682d1d418eSSumit Saxena         iocinit_req.SenseBufferLength = MPI3MR_SENSEBUF_SZ;
21692d1d418eSSumit Saxena         iocinit_req.SenseBufferFreeQueueDepth =
21702d1d418eSSumit Saxena                 sc->sense_buf_q_sz;
21712d1d418eSSumit Saxena         iocinit_req.SenseBufferFreeQueueAddress =
21722d1d418eSSumit Saxena                 sc->sense_buf_q_phys;
21732d1d418eSSumit Saxena         iocinit_req.DriverInformationAddress = drvr_info_phys;
21742d1d418eSSumit Saxena 
21752d1d418eSSumit Saxena 	getmicrotime(&now);
21762d1d418eSSumit Saxena 	time_in_msec = (now.tv_sec * 1000 + now.tv_usec/1000);
21772d1d418eSSumit Saxena 	iocinit_req.TimeStamp = htole64(time_in_msec);
21782d1d418eSSumit Saxena 
2179*3f3a1554SChandrakanth patil 	iocinit_req.MsgFlags |= MPI3_IOCINIT_MSGFLAGS_WRITESAMEDIVERT_SUPPORTED;
2180*3f3a1554SChandrakanth patil 
21812d1d418eSSumit Saxena 	init_completion(&sc->init_cmds.completion);
21822d1d418eSSumit Saxena 	retval = mpi3mr_submit_admin_cmd(sc, &iocinit_req,
21832d1d418eSSumit Saxena 	    sizeof(iocinit_req));
21842d1d418eSSumit Saxena 
21852d1d418eSSumit Saxena 	if (retval) {
21862d1d418eSSumit Saxena 		printf(IOCNAME "Issue IOCInit: Admin Post failed\n",
21872d1d418eSSumit Saxena 		    sc->name);
21882d1d418eSSumit Saxena 		goto out_unlock;
21892d1d418eSSumit Saxena 	}
21902d1d418eSSumit Saxena 
21912d1d418eSSumit Saxena 	wait_for_completion_timeout(&sc->init_cmds.completion,
21922d1d418eSSumit Saxena 	    (MPI3MR_INTADMCMD_TIMEOUT));
21932d1d418eSSumit Saxena 	if (!(sc->init_cmds.state & MPI3MR_CMD_COMPLETE)) {
21942d1d418eSSumit Saxena 		printf(IOCNAME "Issue IOCInit: command timed out\n",
21952d1d418eSSumit Saxena 		    sc->name);
21962d1d418eSSumit Saxena 		mpi3mr_check_rh_fault_ioc(sc,
21972d1d418eSSumit Saxena 		    MPI3MR_RESET_FROM_IOCINIT_TIMEOUT);
21982d1d418eSSumit Saxena 		sc->unrecoverable = 1;
21992d1d418eSSumit Saxena 		retval = -1;
22002d1d418eSSumit Saxena 		goto out_unlock;
22012d1d418eSSumit Saxena 	}
22022d1d418eSSumit Saxena 
22032d1d418eSSumit Saxena 	if ((sc->init_cmds.ioc_status & MPI3_IOCSTATUS_STATUS_MASK)
22042d1d418eSSumit Saxena 	     != MPI3_IOCSTATUS_SUCCESS ) {
22052d1d418eSSumit Saxena 		printf(IOCNAME "Issue IOCInit: Failed IOCStatus(0x%04x) "
22062d1d418eSSumit Saxena 		    " Loginfo(0x%08x) \n" , sc->name,
22072d1d418eSSumit Saxena 		    (sc->init_cmds.ioc_status & MPI3_IOCSTATUS_STATUS_MASK),
22082d1d418eSSumit Saxena 		    sc->init_cmds.ioc_loginfo);
22092d1d418eSSumit Saxena 		retval = -1;
22102d1d418eSSumit Saxena 		goto out_unlock;
22112d1d418eSSumit Saxena 	}
22122d1d418eSSumit Saxena 
22132d1d418eSSumit Saxena out_unlock:
22142d1d418eSSumit Saxena 	sc->init_cmds.state = MPI3MR_CMD_NOTUSED;
22152d1d418eSSumit Saxena 	mtx_unlock(&sc->init_cmds.completion.lock);
22162d1d418eSSumit Saxena 
22172d1d418eSSumit Saxena out:
22182d1d418eSSumit Saxena 	if (drvr_info_phys != 0)
22192d1d418eSSumit Saxena 		bus_dmamap_unload(drvr_info_tag, drvr_info_map);
22202d1d418eSSumit Saxena 	if (drvr_info != NULL)
22212d1d418eSSumit Saxena 		bus_dmamem_free(drvr_info_tag, drvr_info, drvr_info_map);
22222d1d418eSSumit Saxena 	if (drvr_info_tag != NULL)
22232d1d418eSSumit Saxena 		bus_dma_tag_destroy(drvr_info_tag);
22242d1d418eSSumit Saxena 	return retval;
22252d1d418eSSumit Saxena }
22262d1d418eSSumit Saxena 
22272d1d418eSSumit Saxena static void
mpi3mr_display_ioc_info(struct mpi3mr_softc * sc)22282d1d418eSSumit Saxena mpi3mr_display_ioc_info(struct mpi3mr_softc *sc)
22292d1d418eSSumit Saxena {
22302d1d418eSSumit Saxena         int i = 0;
22312d1d418eSSumit Saxena         char personality[16];
22322d1d418eSSumit Saxena 
22332d1d418eSSumit Saxena         switch (sc->facts.personality) {
22342d1d418eSSumit Saxena         case MPI3_IOCFACTS_FLAGS_PERSONALITY_EHBA:
22352d1d418eSSumit Saxena                 strcpy(personality, "Enhanced HBA");
22362d1d418eSSumit Saxena                 break;
22372d1d418eSSumit Saxena         case MPI3_IOCFACTS_FLAGS_PERSONALITY_RAID_DDR:
22382d1d418eSSumit Saxena                 strcpy(personality, "RAID");
22392d1d418eSSumit Saxena                 break;
22402d1d418eSSumit Saxena         default:
22412d1d418eSSumit Saxena                 strcpy(personality, "Unknown");
22422d1d418eSSumit Saxena                 break;
22432d1d418eSSumit Saxena         }
22442d1d418eSSumit Saxena 
22452d1d418eSSumit Saxena 	mpi3mr_dprint(sc, MPI3MR_INFO, "Current Personality: %s\n", personality);
22462d1d418eSSumit Saxena 
224728a27434SWarner Losh 	mpi3mr_dprint(sc, MPI3MR_INFO, "%s\n", sc->fw_version);
22482d1d418eSSumit Saxena 
22492d1d418eSSumit Saxena         mpi3mr_dprint(sc, MPI3MR_INFO, "Protocol=(");
22502d1d418eSSumit Saxena 
22512d1d418eSSumit Saxena         if (sc->facts.protocol_flags &
22522d1d418eSSumit Saxena             MPI3_IOCFACTS_PROTOCOL_SCSI_INITIATOR) {
22532d1d418eSSumit Saxena                 printf("Initiator");
22542d1d418eSSumit Saxena                 i++;
22552d1d418eSSumit Saxena         }
22562d1d418eSSumit Saxena 
22572d1d418eSSumit Saxena         if (sc->facts.protocol_flags &
22582d1d418eSSumit Saxena             MPI3_IOCFACTS_PROTOCOL_SCSI_TARGET) {
22592d1d418eSSumit Saxena                 printf("%sTarget", i ? "," : "");
22602d1d418eSSumit Saxena                 i++;
22612d1d418eSSumit Saxena         }
22622d1d418eSSumit Saxena 
22632d1d418eSSumit Saxena         if (sc->facts.protocol_flags &
22642d1d418eSSumit Saxena             MPI3_IOCFACTS_PROTOCOL_NVME) {
22652d1d418eSSumit Saxena                 printf("%sNVMe attachment", i ? "," : "");
22662d1d418eSSumit Saxena                 i++;
22672d1d418eSSumit Saxena         }
22682d1d418eSSumit Saxena         i = 0;
22692d1d418eSSumit Saxena         printf("), ");
22702d1d418eSSumit Saxena         printf("Capabilities=(");
22712d1d418eSSumit Saxena 
22722d1d418eSSumit Saxena         if (sc->facts.ioc_capabilities &
2273baabb919SChandrakanth patil 	    MPI3_IOCFACTS_CAPABILITY_RAID_SUPPORTED) {
22742d1d418eSSumit Saxena                 printf("RAID");
22752d1d418eSSumit Saxena                 i++;
22762d1d418eSSumit Saxena         }
22772d1d418eSSumit Saxena 
22782d1d418eSSumit Saxena         printf(")\n");
22792d1d418eSSumit Saxena }
22802d1d418eSSumit Saxena 
22812d1d418eSSumit Saxena /**
22822d1d418eSSumit Saxena  * mpi3mr_unmask_events - Unmask events in event mask bitmap
22832d1d418eSSumit Saxena  * @sc: Adapter instance reference
22842d1d418eSSumit Saxena  * @event: MPI event ID
22852d1d418eSSumit Saxena  *
22862d1d418eSSumit Saxena  * Un mask the specific event by resetting the event_mask
22872d1d418eSSumit Saxena  * bitmap.
22882d1d418eSSumit Saxena  *
22892d1d418eSSumit Saxena  * Return: None.
22902d1d418eSSumit Saxena  */
mpi3mr_unmask_events(struct mpi3mr_softc * sc,U16 event)22912d1d418eSSumit Saxena static void mpi3mr_unmask_events(struct mpi3mr_softc *sc, U16 event)
22922d1d418eSSumit Saxena {
22932d1d418eSSumit Saxena 	U32 desired_event;
22942d1d418eSSumit Saxena 
22952d1d418eSSumit Saxena 	if (event >= 128)
22962d1d418eSSumit Saxena 		return;
22972d1d418eSSumit Saxena 
22982d1d418eSSumit Saxena 	desired_event = (1 << (event % 32));
22992d1d418eSSumit Saxena 
23002d1d418eSSumit Saxena 	if (event < 32)
23012d1d418eSSumit Saxena 		sc->event_masks[0] &= ~desired_event;
23022d1d418eSSumit Saxena 	else if (event < 64)
23032d1d418eSSumit Saxena 		sc->event_masks[1] &= ~desired_event;
23042d1d418eSSumit Saxena 	else if (event < 96)
23052d1d418eSSumit Saxena 		sc->event_masks[2] &= ~desired_event;
23062d1d418eSSumit Saxena 	else if (event < 128)
23072d1d418eSSumit Saxena 		sc->event_masks[3] &= ~desired_event;
23082d1d418eSSumit Saxena }
23092d1d418eSSumit Saxena 
mpi3mr_set_events_mask(struct mpi3mr_softc * sc)23102d1d418eSSumit Saxena static void mpi3mr_set_events_mask(struct mpi3mr_softc *sc)
23112d1d418eSSumit Saxena {
23122d1d418eSSumit Saxena 	int i;
23132d1d418eSSumit Saxena 	for (i = 0; i < MPI3_EVENT_NOTIFY_EVENTMASK_WORDS; i++)
23142d1d418eSSumit Saxena 		sc->event_masks[i] = -1;
23152d1d418eSSumit Saxena 
23162d1d418eSSumit Saxena         mpi3mr_unmask_events(sc, MPI3_EVENT_DEVICE_ADDED);
23172d1d418eSSumit Saxena         mpi3mr_unmask_events(sc, MPI3_EVENT_DEVICE_INFO_CHANGED);
23182d1d418eSSumit Saxena         mpi3mr_unmask_events(sc, MPI3_EVENT_DEVICE_STATUS_CHANGE);
23192d1d418eSSumit Saxena 
23202d1d418eSSumit Saxena         mpi3mr_unmask_events(sc, MPI3_EVENT_ENCL_DEVICE_STATUS_CHANGE);
23212d1d418eSSumit Saxena 
23222d1d418eSSumit Saxena         mpi3mr_unmask_events(sc, MPI3_EVENT_SAS_TOPOLOGY_CHANGE_LIST);
23232d1d418eSSumit Saxena         mpi3mr_unmask_events(sc, MPI3_EVENT_SAS_DISCOVERY);
23242d1d418eSSumit Saxena         mpi3mr_unmask_events(sc, MPI3_EVENT_SAS_DEVICE_DISCOVERY_ERROR);
23252d1d418eSSumit Saxena         mpi3mr_unmask_events(sc, MPI3_EVENT_SAS_BROADCAST_PRIMITIVE);
23262d1d418eSSumit Saxena 
23272d1d418eSSumit Saxena         mpi3mr_unmask_events(sc, MPI3_EVENT_PCIE_TOPOLOGY_CHANGE_LIST);
23282d1d418eSSumit Saxena         mpi3mr_unmask_events(sc, MPI3_EVENT_PCIE_ENUMERATION);
23292d1d418eSSumit Saxena 
23302d1d418eSSumit Saxena         mpi3mr_unmask_events(sc, MPI3_EVENT_PREPARE_FOR_RESET);
23312d1d418eSSumit Saxena         mpi3mr_unmask_events(sc, MPI3_EVENT_CABLE_MGMT);
23322d1d418eSSumit Saxena         mpi3mr_unmask_events(sc, MPI3_EVENT_ENERGY_PACK_CHANGE);
23332d1d418eSSumit Saxena }
23342d1d418eSSumit Saxena 
23352d1d418eSSumit Saxena /**
23362d1d418eSSumit Saxena  * mpi3mr_issue_event_notification - Send event notification
23372d1d418eSSumit Saxena  * @sc: Adapter instance reference
23382d1d418eSSumit Saxena  *
23392d1d418eSSumit Saxena  * Issue event notification MPI request through admin queue and
23402d1d418eSSumit Saxena  * wait for the completion of it or time out.
23412d1d418eSSumit Saxena  *
23422d1d418eSSumit Saxena  * Return: 0 on success, non-zero on failures.
23432d1d418eSSumit Saxena  */
mpi3mr_issue_event_notification(struct mpi3mr_softc * sc)23442d1d418eSSumit Saxena int mpi3mr_issue_event_notification(struct mpi3mr_softc *sc)
23452d1d418eSSumit Saxena {
23462d1d418eSSumit Saxena 	Mpi3EventNotificationRequest_t evtnotify_req;
23472d1d418eSSumit Saxena 	int retval = 0;
23482d1d418eSSumit Saxena 	U8 i;
23492d1d418eSSumit Saxena 
23502d1d418eSSumit Saxena 	memset(&evtnotify_req, 0, sizeof(evtnotify_req));
23512d1d418eSSumit Saxena 	mtx_lock(&sc->init_cmds.completion.lock);
23522d1d418eSSumit Saxena 	if (sc->init_cmds.state & MPI3MR_CMD_PENDING) {
23532d1d418eSSumit Saxena 		retval = -1;
23542d1d418eSSumit Saxena 		printf(IOCNAME "Issue EvtNotify: Init command is in use\n",
23552d1d418eSSumit Saxena 		    sc->name);
23562d1d418eSSumit Saxena 		mtx_unlock(&sc->init_cmds.completion.lock);
23572d1d418eSSumit Saxena 		goto out;
23582d1d418eSSumit Saxena 	}
23592d1d418eSSumit Saxena 	sc->init_cmds.state = MPI3MR_CMD_PENDING;
23602d1d418eSSumit Saxena 	sc->init_cmds.is_waiting = 1;
23612d1d418eSSumit Saxena 	sc->init_cmds.callback = NULL;
23622d1d418eSSumit Saxena 	evtnotify_req.HostTag = (MPI3MR_HOSTTAG_INITCMDS);
23632d1d418eSSumit Saxena 	evtnotify_req.Function = MPI3_FUNCTION_EVENT_NOTIFICATION;
23642d1d418eSSumit Saxena 	for (i = 0; i < MPI3_EVENT_NOTIFY_EVENTMASK_WORDS; i++)
23652d1d418eSSumit Saxena 		evtnotify_req.EventMasks[i] =
23662d1d418eSSumit Saxena 		    (sc->event_masks[i]);
23672d1d418eSSumit Saxena 	init_completion(&sc->init_cmds.completion);
23682d1d418eSSumit Saxena 	retval = mpi3mr_submit_admin_cmd(sc, &evtnotify_req,
23692d1d418eSSumit Saxena 	    sizeof(evtnotify_req));
23702d1d418eSSumit Saxena 	if (retval) {
23712d1d418eSSumit Saxena 		printf(IOCNAME "Issue EvtNotify: Admin Post failed\n",
23722d1d418eSSumit Saxena 		    sc->name);
23732d1d418eSSumit Saxena 		goto out_unlock;
23742d1d418eSSumit Saxena 	}
23752d1d418eSSumit Saxena 
23762d1d418eSSumit Saxena 	poll_for_command_completion(sc,
23772d1d418eSSumit Saxena 				    &sc->init_cmds,
23782d1d418eSSumit Saxena 				    (MPI3MR_INTADMCMD_TIMEOUT));
23792d1d418eSSumit Saxena 	if (!(sc->init_cmds.state & MPI3MR_CMD_COMPLETE)) {
23802d1d418eSSumit Saxena 		printf(IOCNAME "Issue EvtNotify: command timed out\n",
23812d1d418eSSumit Saxena 		    sc->name);
23822d1d418eSSumit Saxena 		mpi3mr_check_rh_fault_ioc(sc,
23832d1d418eSSumit Saxena 		    MPI3MR_RESET_FROM_EVTNOTIFY_TIMEOUT);
23842d1d418eSSumit Saxena 		retval = -1;
23852d1d418eSSumit Saxena 		goto out_unlock;
23862d1d418eSSumit Saxena 	}
23872d1d418eSSumit Saxena 
23882d1d418eSSumit Saxena 	if ((sc->init_cmds.ioc_status & MPI3_IOCSTATUS_STATUS_MASK)
23892d1d418eSSumit Saxena 	     != MPI3_IOCSTATUS_SUCCESS ) {
23902d1d418eSSumit Saxena 		printf(IOCNAME "Issue EvtNotify: Failed IOCStatus(0x%04x) "
23912d1d418eSSumit Saxena 		    " Loginfo(0x%08x) \n" , sc->name,
23922d1d418eSSumit Saxena 		    (sc->init_cmds.ioc_status & MPI3_IOCSTATUS_STATUS_MASK),
23932d1d418eSSumit Saxena 		    sc->init_cmds.ioc_loginfo);
23942d1d418eSSumit Saxena 		retval = -1;
23952d1d418eSSumit Saxena 		goto out_unlock;
23962d1d418eSSumit Saxena 	}
23972d1d418eSSumit Saxena 
23982d1d418eSSumit Saxena out_unlock:
23992d1d418eSSumit Saxena 	sc->init_cmds.state = MPI3MR_CMD_NOTUSED;
24002d1d418eSSumit Saxena 	mtx_unlock(&sc->init_cmds.completion.lock);
24012d1d418eSSumit Saxena 
24022d1d418eSSumit Saxena out:
24032d1d418eSSumit Saxena 	return retval;
24042d1d418eSSumit Saxena }
24052d1d418eSSumit Saxena 
24062d1d418eSSumit Saxena int
mpi3mr_register_events(struct mpi3mr_softc * sc)24072d1d418eSSumit Saxena mpi3mr_register_events(struct mpi3mr_softc *sc)
24082d1d418eSSumit Saxena {
24092d1d418eSSumit Saxena 	int error;
24102d1d418eSSumit Saxena 
24112d1d418eSSumit Saxena 	mpi3mr_set_events_mask(sc);
24122d1d418eSSumit Saxena 
24132d1d418eSSumit Saxena 	error = mpi3mr_issue_event_notification(sc);
24142d1d418eSSumit Saxena 
24152d1d418eSSumit Saxena 	if (error) {
24162d1d418eSSumit Saxena 		printf(IOCNAME "Failed to issue event notification %d\n",
24172d1d418eSSumit Saxena 		    sc->name, error);
24182d1d418eSSumit Saxena 	}
24192d1d418eSSumit Saxena 
24202d1d418eSSumit Saxena 	return error;
24212d1d418eSSumit Saxena }
24222d1d418eSSumit Saxena 
24232d1d418eSSumit Saxena /**
24242d1d418eSSumit Saxena  * mpi3mr_process_event_ack - Process event acknowledgment
24252d1d418eSSumit Saxena  * @sc: Adapter instance reference
24262d1d418eSSumit Saxena  * @event: MPI3 event ID
24272d1d418eSSumit Saxena  * @event_ctx: Event context
24282d1d418eSSumit Saxena  *
24292d1d418eSSumit Saxena  * Send event acknowledgement through admin queue and wait for
24302d1d418eSSumit Saxena  * it to complete.
24312d1d418eSSumit Saxena  *
24322d1d418eSSumit Saxena  * Return: 0 on success, non-zero on failures.
24332d1d418eSSumit Saxena  */
mpi3mr_process_event_ack(struct mpi3mr_softc * sc,U8 event,U32 event_ctx)24342d1d418eSSumit Saxena int mpi3mr_process_event_ack(struct mpi3mr_softc *sc, U8 event,
24352d1d418eSSumit Saxena 	U32 event_ctx)
24362d1d418eSSumit Saxena {
24372d1d418eSSumit Saxena 	Mpi3EventAckRequest_t evtack_req;
24382d1d418eSSumit Saxena 	int retval = 0;
24392d1d418eSSumit Saxena 
24402d1d418eSSumit Saxena 	memset(&evtack_req, 0, sizeof(evtack_req));
24412d1d418eSSumit Saxena 	mtx_lock(&sc->init_cmds.completion.lock);
24422d1d418eSSumit Saxena 	if (sc->init_cmds.state & MPI3MR_CMD_PENDING) {
24432d1d418eSSumit Saxena 		retval = -1;
24442d1d418eSSumit Saxena 		printf(IOCNAME "Issue EvtAck: Init command is in use\n",
24452d1d418eSSumit Saxena 		    sc->name);
24462d1d418eSSumit Saxena 		mtx_unlock(&sc->init_cmds.completion.lock);
24472d1d418eSSumit Saxena 		goto out;
24482d1d418eSSumit Saxena 	}
24492d1d418eSSumit Saxena 	sc->init_cmds.state = MPI3MR_CMD_PENDING;
24502d1d418eSSumit Saxena 	sc->init_cmds.is_waiting = 1;
24512d1d418eSSumit Saxena 	sc->init_cmds.callback = NULL;
24522d1d418eSSumit Saxena 	evtack_req.HostTag = htole16(MPI3MR_HOSTTAG_INITCMDS);
24532d1d418eSSumit Saxena 	evtack_req.Function = MPI3_FUNCTION_EVENT_ACK;
24542d1d418eSSumit Saxena 	evtack_req.Event = event;
24552d1d418eSSumit Saxena 	evtack_req.EventContext = htole32(event_ctx);
24562d1d418eSSumit Saxena 
24572d1d418eSSumit Saxena 	init_completion(&sc->init_cmds.completion);
24582d1d418eSSumit Saxena 	retval = mpi3mr_submit_admin_cmd(sc, &evtack_req,
24592d1d418eSSumit Saxena 	    sizeof(evtack_req));
24602d1d418eSSumit Saxena 	if (retval) {
24612d1d418eSSumit Saxena 		printf(IOCNAME "Issue EvtAck: Admin Post failed\n",
24622d1d418eSSumit Saxena 		    sc->name);
24632d1d418eSSumit Saxena 		goto out_unlock;
24642d1d418eSSumit Saxena 	}
24652d1d418eSSumit Saxena 
24662d1d418eSSumit Saxena 	wait_for_completion_timeout(&sc->init_cmds.completion,
24672d1d418eSSumit Saxena 	    (MPI3MR_INTADMCMD_TIMEOUT));
24682d1d418eSSumit Saxena 	if (!(sc->init_cmds.state & MPI3MR_CMD_COMPLETE)) {
24692d1d418eSSumit Saxena 		printf(IOCNAME "Issue EvtAck: command timed out\n",
24702d1d418eSSumit Saxena 		    sc->name);
24712d1d418eSSumit Saxena 		retval = -1;
24722d1d418eSSumit Saxena 		goto out_unlock;
24732d1d418eSSumit Saxena 	}
24742d1d418eSSumit Saxena 
24752d1d418eSSumit Saxena 	if ((sc->init_cmds.ioc_status & MPI3_IOCSTATUS_STATUS_MASK)
24762d1d418eSSumit Saxena 	     != MPI3_IOCSTATUS_SUCCESS ) {
24772d1d418eSSumit Saxena 		printf(IOCNAME "Issue EvtAck: Failed IOCStatus(0x%04x) "
24782d1d418eSSumit Saxena 		    " Loginfo(0x%08x) \n" , sc->name,
24792d1d418eSSumit Saxena 		    (sc->init_cmds.ioc_status & MPI3_IOCSTATUS_STATUS_MASK),
24802d1d418eSSumit Saxena 		    sc->init_cmds.ioc_loginfo);
24812d1d418eSSumit Saxena 		retval = -1;
24822d1d418eSSumit Saxena 		goto out_unlock;
24832d1d418eSSumit Saxena 	}
24842d1d418eSSumit Saxena 
24852d1d418eSSumit Saxena out_unlock:
24862d1d418eSSumit Saxena 	sc->init_cmds.state = MPI3MR_CMD_NOTUSED;
24872d1d418eSSumit Saxena 	mtx_unlock(&sc->init_cmds.completion.lock);
24882d1d418eSSumit Saxena 
24892d1d418eSSumit Saxena out:
24902d1d418eSSumit Saxena 	return retval;
24912d1d418eSSumit Saxena }
24922d1d418eSSumit Saxena 
24932d1d418eSSumit Saxena 
mpi3mr_alloc_chain_bufs(struct mpi3mr_softc * sc)24942d1d418eSSumit Saxena static int mpi3mr_alloc_chain_bufs(struct mpi3mr_softc *sc)
24952d1d418eSSumit Saxena {
24962d1d418eSSumit Saxena 	int retval = 0;
24972d1d418eSSumit Saxena 	U32 sz, i;
24982d1d418eSSumit Saxena 	U16 num_chains;
24992d1d418eSSumit Saxena 
25002d1d418eSSumit Saxena 	num_chains = sc->max_host_ios;
25012d1d418eSSumit Saxena 
25022d1d418eSSumit Saxena 	sc->chain_buf_count = num_chains;
25032d1d418eSSumit Saxena 	sz = sizeof(struct mpi3mr_chain) * num_chains;
25042d1d418eSSumit Saxena 
25052d1d418eSSumit Saxena 	sc->chain_sgl_list = malloc(sz, M_MPI3MR, M_NOWAIT | M_ZERO);
25062d1d418eSSumit Saxena 
25072d1d418eSSumit Saxena 	if (!sc->chain_sgl_list) {
25082d1d418eSSumit Saxena 		printf(IOCNAME "Cannot allocate memory for chain SGL list\n",
25092d1d418eSSumit Saxena 		    sc->name);
25102d1d418eSSumit Saxena 		retval = -1;
25112d1d418eSSumit Saxena 		goto out_failed;
25122d1d418eSSumit Saxena 	}
25132d1d418eSSumit Saxena 
25142d1d418eSSumit Saxena 	sz = MPI3MR_CHAINSGE_SIZE;
25152d1d418eSSumit Saxena 
25162d1d418eSSumit Saxena         if (bus_dma_tag_create(sc->mpi3mr_parent_dmat,  /* parent */
25172d1d418eSSumit Saxena 				4096, 0,		/* algnmnt, boundary */
2518ee7c431cSWarner Losh 				sc->dma_loaddr,		/* lowaddr */
25191ec7c672SWarner Losh 				BUS_SPACE_MAXADDR,	/* highaddr */
25202d1d418eSSumit Saxena 				NULL, NULL,		/* filter, filterarg */
25212d1d418eSSumit Saxena                                 sz,			/* maxsize */
25222d1d418eSSumit Saxena                                 1,			/* nsegments */
25232d1d418eSSumit Saxena                                 sz,			/* maxsegsize */
25242d1d418eSSumit Saxena                                 0,			/* flags */
25252d1d418eSSumit Saxena                                 NULL, NULL,		/* lockfunc, lockarg */
25262d1d418eSSumit Saxena                                 &sc->chain_sgl_list_tag)) {
25272d1d418eSSumit Saxena 		mpi3mr_dprint(sc, MPI3MR_ERROR, "Cannot allocate Chain buffer DMA tag\n");
25282d1d418eSSumit Saxena 		return (ENOMEM);
25292d1d418eSSumit Saxena         }
25302d1d418eSSumit Saxena 
25312d1d418eSSumit Saxena 	for (i = 0; i < num_chains; i++) {
25322d1d418eSSumit Saxena 		if (bus_dmamem_alloc(sc->chain_sgl_list_tag, (void **)&sc->chain_sgl_list[i].buf,
25332d1d418eSSumit Saxena 		    BUS_DMA_NOWAIT, &sc->chain_sgl_list[i].buf_dmamap)) {
25342d1d418eSSumit Saxena 			mpi3mr_dprint(sc, MPI3MR_ERROR, "Func: %s line: %d  DMA mem alloc failed\n",
25352d1d418eSSumit Saxena 				__func__, __LINE__);
25362d1d418eSSumit Saxena 			return (ENOMEM);
25372d1d418eSSumit Saxena 		}
25382d1d418eSSumit Saxena 
25392d1d418eSSumit Saxena 		bzero(sc->chain_sgl_list[i].buf, sz);
25402d1d418eSSumit Saxena 		bus_dmamap_load(sc->chain_sgl_list_tag, sc->chain_sgl_list[i].buf_dmamap, sc->chain_sgl_list[i].buf, sz,
254139a3e6a8SAlexander Motin 		    mpi3mr_memaddr_cb, &sc->chain_sgl_list[i].buf_phys, BUS_DMA_NOWAIT);
25422d1d418eSSumit Saxena 		mpi3mr_dprint(sc, MPI3MR_XINFO, "Func: %s line: %d phys addr= %#016jx size= %d\n",
25432d1d418eSSumit Saxena 		    __func__, __LINE__, (uintmax_t)sc->chain_sgl_list[i].buf_phys, sz);
25442d1d418eSSumit Saxena 	}
25452d1d418eSSumit Saxena 
25462d1d418eSSumit Saxena 	sc->chain_bitmap_sz = MPI3MR_DIV_ROUND_UP(num_chains, 8);
25472d1d418eSSumit Saxena 
25482d1d418eSSumit Saxena 	sc->chain_bitmap = malloc(sc->chain_bitmap_sz, M_MPI3MR, M_NOWAIT | M_ZERO);
25492d1d418eSSumit Saxena 	if (!sc->chain_bitmap) {
25502d1d418eSSumit Saxena 		mpi3mr_dprint(sc, MPI3MR_INFO, "Cannot alloc memory for chain bitmap\n");
25512d1d418eSSumit Saxena 		retval = -1;
25522d1d418eSSumit Saxena 		goto out_failed;
25532d1d418eSSumit Saxena 	}
25542d1d418eSSumit Saxena 	return retval;
25552d1d418eSSumit Saxena 
25562d1d418eSSumit Saxena out_failed:
25572d1d418eSSumit Saxena 	for (i = 0; i < num_chains; i++) {
25582d1d418eSSumit Saxena 		if (sc->chain_sgl_list[i].buf_phys != 0)
25592d1d418eSSumit Saxena 			bus_dmamap_unload(sc->chain_sgl_list_tag, sc->chain_sgl_list[i].buf_dmamap);
25602d1d418eSSumit Saxena 		if (sc->chain_sgl_list[i].buf != NULL)
25612d1d418eSSumit Saxena 			bus_dmamem_free(sc->chain_sgl_list_tag, sc->chain_sgl_list[i].buf, sc->chain_sgl_list[i].buf_dmamap);
25622d1d418eSSumit Saxena 	}
25632d1d418eSSumit Saxena 	if (sc->chain_sgl_list_tag != NULL)
25642d1d418eSSumit Saxena 		bus_dma_tag_destroy(sc->chain_sgl_list_tag);
25652d1d418eSSumit Saxena 	return retval;
25662d1d418eSSumit Saxena }
25672d1d418eSSumit Saxena 
mpi3mr_pel_alloc(struct mpi3mr_softc * sc)25682d1d418eSSumit Saxena static int mpi3mr_pel_alloc(struct mpi3mr_softc *sc)
25692d1d418eSSumit Saxena {
25702d1d418eSSumit Saxena 	int retval = 0;
25712d1d418eSSumit Saxena 
25722d1d418eSSumit Saxena 	if (!sc->pel_cmds.reply) {
25732d1d418eSSumit Saxena 		sc->pel_cmds.reply = malloc(sc->reply_sz, M_MPI3MR, M_NOWAIT | M_ZERO);
25742d1d418eSSumit Saxena 		if (!sc->pel_cmds.reply) {
25752d1d418eSSumit Saxena 			printf(IOCNAME "Cannot allocate memory for pel_cmds.reply\n",
25762d1d418eSSumit Saxena 			    sc->name);
25772d1d418eSSumit Saxena 			goto out_failed;
25782d1d418eSSumit Saxena 		}
25792d1d418eSSumit Saxena 	}
25802d1d418eSSumit Saxena 
25812d1d418eSSumit Saxena 	if (!sc->pel_abort_cmd.reply) {
25822d1d418eSSumit Saxena 		sc->pel_abort_cmd.reply = malloc(sc->reply_sz, M_MPI3MR, M_NOWAIT | M_ZERO);
25832d1d418eSSumit Saxena 		if (!sc->pel_abort_cmd.reply) {
25842d1d418eSSumit Saxena 			printf(IOCNAME "Cannot allocate memory for pel_abort_cmd.reply\n",
25852d1d418eSSumit Saxena 			    sc->name);
25862d1d418eSSumit Saxena 			goto out_failed;
25872d1d418eSSumit Saxena 		}
25882d1d418eSSumit Saxena 	}
25892d1d418eSSumit Saxena 
25902d1d418eSSumit Saxena 	if (!sc->pel_seq_number) {
25912d1d418eSSumit Saxena 		sc->pel_seq_number_sz = sizeof(Mpi3PELSeq_t);
25922d1d418eSSumit Saxena 		if (bus_dma_tag_create(sc->mpi3mr_parent_dmat,   /* parent */
25932d1d418eSSumit Saxena 				 4, 0,                           /* alignment, boundary */
2594ee7c431cSWarner Losh 				 sc->dma_loaddr,	         /* lowaddr */
25951ec7c672SWarner Losh 				 BUS_SPACE_MAXADDR,		 /* highaddr */
25962d1d418eSSumit Saxena 				 NULL, NULL,                     /* filter, filterarg */
25972d1d418eSSumit Saxena 				 sc->pel_seq_number_sz,		 /* maxsize */
25982d1d418eSSumit Saxena 				 1,                              /* nsegments */
25992d1d418eSSumit Saxena 				 sc->pel_seq_number_sz,          /* maxsegsize */
26002d1d418eSSumit Saxena 				 0,                              /* flags */
26012d1d418eSSumit Saxena 				 NULL, NULL,                     /* lockfunc, lockarg */
26022d1d418eSSumit Saxena 				 &sc->pel_seq_num_dmatag)) {
26032d1d418eSSumit Saxena 			 mpi3mr_dprint(sc, MPI3MR_ERROR, "Cannot create PEL seq number dma memory tag\n");
26042d1d418eSSumit Saxena 			 retval = -ENOMEM;
26052d1d418eSSumit Saxena 			 goto out_failed;
26062d1d418eSSumit Saxena 		}
26072d1d418eSSumit Saxena 
26082d1d418eSSumit Saxena 		if (bus_dmamem_alloc(sc->pel_seq_num_dmatag, (void **)&sc->pel_seq_number,
26092d1d418eSSumit Saxena 		    BUS_DMA_NOWAIT, &sc->pel_seq_num_dmamap)) {
26102d1d418eSSumit Saxena 			mpi3mr_dprint(sc, MPI3MR_ERROR, "Cannot allocate PEL seq number kernel buffer dma memory\n");
26112d1d418eSSumit Saxena 			retval = -ENOMEM;
26122d1d418eSSumit Saxena 			goto out_failed;
26132d1d418eSSumit Saxena 		}
26142d1d418eSSumit Saxena 
26152d1d418eSSumit Saxena 		bzero(sc->pel_seq_number, sc->pel_seq_number_sz);
26162d1d418eSSumit Saxena 
26172d1d418eSSumit Saxena 		bus_dmamap_load(sc->pel_seq_num_dmatag, sc->pel_seq_num_dmamap, sc->pel_seq_number,
261839a3e6a8SAlexander Motin 		    sc->pel_seq_number_sz, mpi3mr_memaddr_cb, &sc->pel_seq_number_dma, BUS_DMA_NOWAIT);
26192d1d418eSSumit Saxena 
26202d1d418eSSumit Saxena 		if (!sc->pel_seq_number) {
26212d1d418eSSumit Saxena 			printf(IOCNAME "%s:%d Cannot load PEL seq number dma memory for size: %d\n", sc->name,
26222d1d418eSSumit Saxena 				__func__, __LINE__, sc->pel_seq_number_sz);
26232d1d418eSSumit Saxena 			retval = -ENOMEM;
26242d1d418eSSumit Saxena 			goto out_failed;
26252d1d418eSSumit Saxena 		}
26262d1d418eSSumit Saxena 	}
26272d1d418eSSumit Saxena 
26282d1d418eSSumit Saxena out_failed:
26292d1d418eSSumit Saxena 	return retval;
26302d1d418eSSumit Saxena }
26312d1d418eSSumit Saxena 
26322d1d418eSSumit Saxena /**
26332d1d418eSSumit Saxena  * mpi3mr_validate_fw_update - validate IOCFacts post adapter reset
26342d1d418eSSumit Saxena  * @sc: Adapter instance reference
26352d1d418eSSumit Saxena  *
26362d1d418eSSumit Saxena  * Return zero if the new IOCFacts is compatible with previous values
26372d1d418eSSumit Saxena  * else return appropriate error
26382d1d418eSSumit Saxena  */
26392d1d418eSSumit Saxena static int
mpi3mr_validate_fw_update(struct mpi3mr_softc * sc)26402d1d418eSSumit Saxena mpi3mr_validate_fw_update(struct mpi3mr_softc *sc)
26412d1d418eSSumit Saxena {
26422d1d418eSSumit Saxena 	U16 dev_handle_bitmap_sz;
26432d1d418eSSumit Saxena 	U8 *removepend_bitmap;
26442d1d418eSSumit Saxena 
26452d1d418eSSumit Saxena 	if (sc->facts.reply_sz > sc->reply_sz) {
26462d1d418eSSumit Saxena 		mpi3mr_dprint(sc, MPI3MR_ERROR,
26472d1d418eSSumit Saxena 		    "Cannot increase reply size from %d to %d\n",
26482d1d418eSSumit Saxena 		    sc->reply_sz, sc->reply_sz);
26492d1d418eSSumit Saxena 		return -EPERM;
26502d1d418eSSumit Saxena 	}
26512d1d418eSSumit Saxena 
26522d1d418eSSumit Saxena 	if (sc->num_io_throttle_group != sc->facts.max_io_throttle_group) {
26532d1d418eSSumit Saxena 		mpi3mr_dprint(sc, MPI3MR_ERROR,
26542d1d418eSSumit Saxena 		    "max io throttle group doesn't match old(%d), new(%d)\n",
26552d1d418eSSumit Saxena 		    sc->num_io_throttle_group,
26562d1d418eSSumit Saxena 		    sc->facts.max_io_throttle_group);
26572d1d418eSSumit Saxena 		return -EPERM;
26582d1d418eSSumit Saxena 	}
26592d1d418eSSumit Saxena 
26602d1d418eSSumit Saxena 	if (sc->facts.max_op_reply_q < sc->num_queues) {
26612d1d418eSSumit Saxena 		mpi3mr_dprint(sc, MPI3MR_ERROR,
26622d1d418eSSumit Saxena 		    "Cannot reduce number of operational reply queues from %d to %d\n",
26632d1d418eSSumit Saxena 		    sc->num_queues,
26642d1d418eSSumit Saxena 		    sc->facts.max_op_reply_q);
26652d1d418eSSumit Saxena 		return -EPERM;
26662d1d418eSSumit Saxena 	}
26672d1d418eSSumit Saxena 
26682d1d418eSSumit Saxena 	if (sc->facts.max_op_req_q < sc->num_queues) {
26692d1d418eSSumit Saxena 		mpi3mr_dprint(sc, MPI3MR_ERROR,
26702d1d418eSSumit Saxena 		    "Cannot reduce number of operational request queues from %d to %d\n",
26712d1d418eSSumit Saxena 		    sc->num_queues, sc->facts.max_op_req_q);
26722d1d418eSSumit Saxena 		return -EPERM;
26732d1d418eSSumit Saxena 	}
26742d1d418eSSumit Saxena 
26752d1d418eSSumit Saxena 	dev_handle_bitmap_sz = MPI3MR_DIV_ROUND_UP(sc->facts.max_devhandle, 8);
26762d1d418eSSumit Saxena 
26772d1d418eSSumit Saxena 	if (dev_handle_bitmap_sz > sc->dev_handle_bitmap_sz) {
26782d1d418eSSumit Saxena 		removepend_bitmap = realloc(sc->removepend_bitmap,
26792d1d418eSSumit Saxena 		    dev_handle_bitmap_sz, M_MPI3MR, M_NOWAIT);
26802d1d418eSSumit Saxena 
26812d1d418eSSumit Saxena 		if (!removepend_bitmap) {
26822d1d418eSSumit Saxena 			mpi3mr_dprint(sc, MPI3MR_ERROR,
26832d1d418eSSumit Saxena 			    "failed to increase removepend_bitmap sz from: %d to %d\n",
26842d1d418eSSumit Saxena 			    sc->dev_handle_bitmap_sz, dev_handle_bitmap_sz);
26852d1d418eSSumit Saxena 			return -ENOMEM;
26862d1d418eSSumit Saxena 		}
26872d1d418eSSumit Saxena 
26882d1d418eSSumit Saxena 		memset(removepend_bitmap + sc->dev_handle_bitmap_sz, 0,
26892d1d418eSSumit Saxena 		    dev_handle_bitmap_sz - sc->dev_handle_bitmap_sz);
26902d1d418eSSumit Saxena 		sc->removepend_bitmap = removepend_bitmap;
26912d1d418eSSumit Saxena 		mpi3mr_dprint(sc, MPI3MR_INFO,
26922d1d418eSSumit Saxena 		    "increased dev_handle_bitmap_sz from %d to %d\n",
26932d1d418eSSumit Saxena 		    sc->dev_handle_bitmap_sz, dev_handle_bitmap_sz);
26942d1d418eSSumit Saxena 		sc->dev_handle_bitmap_sz = dev_handle_bitmap_sz;
26952d1d418eSSumit Saxena 	}
26962d1d418eSSumit Saxena 
26972d1d418eSSumit Saxena 	return 0;
26982d1d418eSSumit Saxena }
26992d1d418eSSumit Saxena 
27002d1d418eSSumit Saxena /*
27012d1d418eSSumit Saxena  * mpi3mr_initialize_ioc - Controller initialization
27022d1d418eSSumit Saxena  * @dev: pointer to device struct
27032d1d418eSSumit Saxena  *
27042d1d418eSSumit Saxena  * This function allocates the controller wide resources and brings
27052d1d418eSSumit Saxena  * the controller to operational state
27062d1d418eSSumit Saxena  *
27072d1d418eSSumit Saxena  * Return: 0 on success and proper error codes on failure
27082d1d418eSSumit Saxena  */
mpi3mr_initialize_ioc(struct mpi3mr_softc * sc,U8 init_type)27092d1d418eSSumit Saxena int mpi3mr_initialize_ioc(struct mpi3mr_softc *sc, U8 init_type)
27102d1d418eSSumit Saxena {
27112d1d418eSSumit Saxena 	int retval = 0;
27122d1d418eSSumit Saxena 	enum mpi3mr_iocstate ioc_state;
27132d1d418eSSumit Saxena 	U64 ioc_info;
27142d1d418eSSumit Saxena 	U32 ioc_status, ioc_control, i, timeout;
27152d1d418eSSumit Saxena 	Mpi3IOCFactsData_t facts_data;
27162d1d418eSSumit Saxena 	char str[32];
27172d1d418eSSumit Saxena 	U32 size;
27182d1d418eSSumit Saxena 
27192d1d418eSSumit Saxena 	sc->cpu_count = mp_ncpus;
27202d1d418eSSumit Saxena 
27212d1d418eSSumit Saxena 	ioc_status = mpi3mr_regread(sc, MPI3_SYSIF_IOC_STATUS_OFFSET);
27222d1d418eSSumit Saxena 	ioc_control = mpi3mr_regread(sc, MPI3_SYSIF_IOC_CONFIG_OFFSET);
27232d1d418eSSumit Saxena 	ioc_info = mpi3mr_regread64(sc, MPI3_SYSIF_IOC_INFO_LOW_OFFSET);
27242d1d418eSSumit Saxena 
27252d1d418eSSumit Saxena 	mpi3mr_dprint(sc, MPI3MR_INFO, "SOD ioc_status: 0x%x ioc_control: 0x%x "
27262d1d418eSSumit Saxena 	    "ioc_info: 0x%lx\n", ioc_status, ioc_control, ioc_info);
27272d1d418eSSumit Saxena 
27282d1d418eSSumit Saxena         /*The timeout value is in 2sec unit, changing it to seconds*/
27292d1d418eSSumit Saxena 	sc->ready_timeout =
27302d1d418eSSumit Saxena                 ((ioc_info & MPI3_SYSIF_IOC_INFO_LOW_TIMEOUT_MASK) >>
27312d1d418eSSumit Saxena                     MPI3_SYSIF_IOC_INFO_LOW_TIMEOUT_SHIFT) * 2;
27322d1d418eSSumit Saxena 
27332d1d418eSSumit Saxena 	ioc_state = mpi3mr_get_iocstate(sc);
27342d1d418eSSumit Saxena 
27352d1d418eSSumit Saxena 	mpi3mr_dprint(sc, MPI3MR_INFO, "IOC state: %s   IOC ready timeout: %d\n",
27362d1d418eSSumit Saxena 	    mpi3mr_iocstate_name(ioc_state), sc->ready_timeout);
27372d1d418eSSumit Saxena 
27382d1d418eSSumit Saxena 	if (ioc_state == MRIOC_STATE_BECOMING_READY ||
27392d1d418eSSumit Saxena 	    ioc_state == MRIOC_STATE_RESET_REQUESTED) {
27402d1d418eSSumit Saxena 		timeout = sc->ready_timeout * 10;
27412d1d418eSSumit Saxena 		do {
27422d1d418eSSumit Saxena 			DELAY(1000 * 100);
27432d1d418eSSumit Saxena 		} while (--timeout);
27442d1d418eSSumit Saxena 
27452d1d418eSSumit Saxena 		ioc_state = mpi3mr_get_iocstate(sc);
27462d1d418eSSumit Saxena 		mpi3mr_dprint(sc, MPI3MR_INFO,
27472d1d418eSSumit Saxena 			"IOC in %s state after waiting for reset time\n",
27482d1d418eSSumit Saxena 			mpi3mr_iocstate_name(ioc_state));
27492d1d418eSSumit Saxena 	}
27502d1d418eSSumit Saxena 
27512d1d418eSSumit Saxena 	if (ioc_state == MRIOC_STATE_READY) {
27522d1d418eSSumit Saxena                 retval = mpi3mr_mur_ioc(sc, MPI3MR_RESET_FROM_BRINGUP);
27532d1d418eSSumit Saxena                 if (retval) {
27542d1d418eSSumit Saxena                         mpi3mr_dprint(sc, MPI3MR_ERROR, "Failed to MU reset IOC, error 0x%x\n",
27552d1d418eSSumit Saxena                                 retval);
27562d1d418eSSumit Saxena                 }
27572d1d418eSSumit Saxena                 ioc_state = mpi3mr_get_iocstate(sc);
27582d1d418eSSumit Saxena         }
27592d1d418eSSumit Saxena 
27602d1d418eSSumit Saxena         if (ioc_state != MRIOC_STATE_RESET) {
27612d1d418eSSumit Saxena                 mpi3mr_print_fault_info(sc);
27622d1d418eSSumit Saxena 		 mpi3mr_dprint(sc, MPI3MR_ERROR, "issuing soft reset to bring to reset state\n");
27632d1d418eSSumit Saxena                  retval = mpi3mr_issue_reset(sc,
27642d1d418eSSumit Saxena                      MPI3_SYSIF_HOST_DIAG_RESET_ACTION_SOFT_RESET,
27652d1d418eSSumit Saxena                      MPI3MR_RESET_FROM_BRINGUP);
27662d1d418eSSumit Saxena                 if (retval) {
27672d1d418eSSumit Saxena                         mpi3mr_dprint(sc, MPI3MR_ERROR,
27682d1d418eSSumit Saxena                             "%s :Failed to soft reset IOC, error 0x%d\n",
27692d1d418eSSumit Saxena                             __func__, retval);
27702d1d418eSSumit Saxena                         goto out_failed;
27712d1d418eSSumit Saxena                 }
27722d1d418eSSumit Saxena         }
27732d1d418eSSumit Saxena 
27742d1d418eSSumit Saxena 	ioc_state = mpi3mr_get_iocstate(sc);
27752d1d418eSSumit Saxena 
27762d1d418eSSumit Saxena         if (ioc_state != MRIOC_STATE_RESET) {
27772d1d418eSSumit Saxena 		mpi3mr_dprint(sc, MPI3MR_ERROR, "Cannot bring IOC to reset state\n");
27782d1d418eSSumit Saxena 		goto out_failed;
27792d1d418eSSumit Saxena         }
27802d1d418eSSumit Saxena 
27812d1d418eSSumit Saxena 	retval = mpi3mr_setup_admin_qpair(sc);
27822d1d418eSSumit Saxena 	if (retval) {
27832d1d418eSSumit Saxena 		mpi3mr_dprint(sc, MPI3MR_ERROR, "Failed to setup Admin queues, error 0x%x\n",
27842d1d418eSSumit Saxena 		    retval);
27852d1d418eSSumit Saxena 		goto out_failed;
27862d1d418eSSumit Saxena 	}
27872d1d418eSSumit Saxena 
27882d1d418eSSumit Saxena 	retval = mpi3mr_bring_ioc_ready(sc);
27892d1d418eSSumit Saxena 	if (retval) {
27902d1d418eSSumit Saxena 		mpi3mr_dprint(sc, MPI3MR_ERROR, "Failed to bring IOC ready, error 0x%x\n",
27912d1d418eSSumit Saxena 		    retval);
27922d1d418eSSumit Saxena 		goto out_failed;
27932d1d418eSSumit Saxena 	}
27942d1d418eSSumit Saxena 
27952d1d418eSSumit Saxena 	if (init_type == MPI3MR_INIT_TYPE_INIT) {
27962d1d418eSSumit Saxena 		retval = mpi3mr_alloc_interrupts(sc, 1);
27972d1d418eSSumit Saxena 		if (retval) {
27982d1d418eSSumit Saxena 			mpi3mr_dprint(sc, MPI3MR_ERROR, "Failed to allocate interrupts, error 0x%x\n",
27992d1d418eSSumit Saxena 			    retval);
28002d1d418eSSumit Saxena 			goto out_failed;
28012d1d418eSSumit Saxena 		}
28022d1d418eSSumit Saxena 
28032d1d418eSSumit Saxena 		retval = mpi3mr_setup_irqs(sc);
28042d1d418eSSumit Saxena 		if (retval) {
28052d1d418eSSumit Saxena 			mpi3mr_dprint(sc, MPI3MR_ERROR, "Failed to setup ISR, error 0x%x\n",
28062d1d418eSSumit Saxena 			    retval);
28072d1d418eSSumit Saxena 			goto out_failed;
28082d1d418eSSumit Saxena 		}
28092d1d418eSSumit Saxena 	}
28102d1d418eSSumit Saxena 
28112d1d418eSSumit Saxena 	mpi3mr_enable_interrupts(sc);
28122d1d418eSSumit Saxena 
28132d1d418eSSumit Saxena 	if (init_type == MPI3MR_INIT_TYPE_INIT) {
28142d1d418eSSumit Saxena 		mtx_init(&sc->mpi3mr_mtx, "SIM lock", NULL, MTX_DEF);
28152d1d418eSSumit Saxena 		mtx_init(&sc->io_lock, "IO lock", NULL, MTX_DEF);
28162d1d418eSSumit Saxena 		mtx_init(&sc->admin_req_lock, "Admin Request Queue lock", NULL, MTX_SPIN);
28172d1d418eSSumit Saxena 		mtx_init(&sc->reply_free_q_lock, "Reply free Queue lock", NULL, MTX_SPIN);
28182d1d418eSSumit Saxena 		mtx_init(&sc->sense_buf_q_lock, "Sense buffer Queue lock", NULL, MTX_SPIN);
28192d1d418eSSumit Saxena 		mtx_init(&sc->chain_buf_lock, "Chain buffer lock", NULL, MTX_SPIN);
28202d1d418eSSumit Saxena 		mtx_init(&sc->cmd_pool_lock, "Command pool lock", NULL, MTX_DEF);
28212d1d418eSSumit Saxena 		mtx_init(&sc->fwevt_lock, "Firmware Event lock", NULL, MTX_DEF);
28222d1d418eSSumit Saxena 		mtx_init(&sc->target_lock, "Target lock", NULL, MTX_SPIN);
28232d1d418eSSumit Saxena 		mtx_init(&sc->reset_mutex, "Reset lock", NULL, MTX_DEF);
28242d1d418eSSumit Saxena 
28252d1d418eSSumit Saxena 		mtx_init(&sc->init_cmds.completion.lock, "Init commands lock", NULL, MTX_DEF);
28262d1d418eSSumit Saxena 		sc->init_cmds.reply = NULL;
28272d1d418eSSumit Saxena 		sc->init_cmds.state = MPI3MR_CMD_NOTUSED;
28282d1d418eSSumit Saxena 		sc->init_cmds.dev_handle = MPI3MR_INVALID_DEV_HANDLE;
28292d1d418eSSumit Saxena 		sc->init_cmds.host_tag = MPI3MR_HOSTTAG_INITCMDS;
28302d1d418eSSumit Saxena 
28312d1d418eSSumit Saxena 		mtx_init(&sc->ioctl_cmds.completion.lock, "IOCTL commands lock", NULL, MTX_DEF);
28322d1d418eSSumit Saxena 		sc->ioctl_cmds.reply = NULL;
28332d1d418eSSumit Saxena 		sc->ioctl_cmds.state = MPI3MR_CMD_NOTUSED;
28342d1d418eSSumit Saxena 		sc->ioctl_cmds.dev_handle = MPI3MR_INVALID_DEV_HANDLE;
28352d1d418eSSumit Saxena 		sc->ioctl_cmds.host_tag = MPI3MR_HOSTTAG_IOCTLCMDS;
28362d1d418eSSumit Saxena 
28372d1d418eSSumit Saxena 		mtx_init(&sc->pel_abort_cmd.completion.lock, "PEL Abort command lock", NULL, MTX_DEF);
28382d1d418eSSumit Saxena 		sc->pel_abort_cmd.reply = NULL;
28392d1d418eSSumit Saxena 		sc->pel_abort_cmd.state = MPI3MR_CMD_NOTUSED;
28402d1d418eSSumit Saxena 		sc->pel_abort_cmd.dev_handle = MPI3MR_INVALID_DEV_HANDLE;
28412d1d418eSSumit Saxena 		sc->pel_abort_cmd.host_tag = MPI3MR_HOSTTAG_PELABORT;
28422d1d418eSSumit Saxena 
28432d1d418eSSumit Saxena 		mtx_init(&sc->host_tm_cmds.completion.lock, "TM commands lock", NULL, MTX_DEF);
28442d1d418eSSumit Saxena 		sc->host_tm_cmds.reply = NULL;
28452d1d418eSSumit Saxena 		sc->host_tm_cmds.state = MPI3MR_CMD_NOTUSED;
28462d1d418eSSumit Saxena 		sc->host_tm_cmds.dev_handle = MPI3MR_INVALID_DEV_HANDLE;
28472d1d418eSSumit Saxena 		sc->host_tm_cmds.host_tag = MPI3MR_HOSTTAG_TMS;
28482d1d418eSSumit Saxena 
28492d1d418eSSumit Saxena 		TAILQ_INIT(&sc->cmd_list_head);
28502d1d418eSSumit Saxena 		TAILQ_INIT(&sc->event_list);
28512d1d418eSSumit Saxena 		TAILQ_INIT(&sc->delayed_rmhs_list);
28522d1d418eSSumit Saxena 		TAILQ_INIT(&sc->delayed_evtack_cmds_list);
28532d1d418eSSumit Saxena 
28542d1d418eSSumit Saxena 		for (i = 0; i < MPI3MR_NUM_DEVRMCMD; i++) {
28552d1d418eSSumit Saxena 			snprintf(str, 32, "Dev REMHS commands lock[%d]", i);
28562d1d418eSSumit Saxena 			mtx_init(&sc->dev_rmhs_cmds[i].completion.lock, str, NULL, MTX_DEF);
28572d1d418eSSumit Saxena 			sc->dev_rmhs_cmds[i].reply = NULL;
28582d1d418eSSumit Saxena 			sc->dev_rmhs_cmds[i].state = MPI3MR_CMD_NOTUSED;
28592d1d418eSSumit Saxena 			sc->dev_rmhs_cmds[i].dev_handle = MPI3MR_INVALID_DEV_HANDLE;
28602d1d418eSSumit Saxena 			sc->dev_rmhs_cmds[i].host_tag = MPI3MR_HOSTTAG_DEVRMCMD_MIN
28612d1d418eSSumit Saxena 							    + i;
28622d1d418eSSumit Saxena 		}
28632d1d418eSSumit Saxena 	}
28642d1d418eSSumit Saxena 
28652d1d418eSSumit Saxena 	retval = mpi3mr_issue_iocfacts(sc, &facts_data);
28662d1d418eSSumit Saxena 	if (retval) {
28672d1d418eSSumit Saxena 		mpi3mr_dprint(sc, MPI3MR_ERROR, "Failed to Issue IOC Facts, retval: 0x%x\n",
28682d1d418eSSumit Saxena 		    retval);
28692d1d418eSSumit Saxena 		goto out_failed;
28702d1d418eSSumit Saxena 	}
28712d1d418eSSumit Saxena 
28722d1d418eSSumit Saxena 	retval = mpi3mr_process_factsdata(sc, &facts_data);
28732d1d418eSSumit Saxena 	if (retval) {
28742d1d418eSSumit Saxena 		mpi3mr_dprint(sc, MPI3MR_ERROR, "IOC Facts data processing failedi, retval: 0x%x\n",
28752d1d418eSSumit Saxena 		    retval);
28762d1d418eSSumit Saxena 		goto out_failed;
28772d1d418eSSumit Saxena 	}
28782d1d418eSSumit Saxena 
28792d1d418eSSumit Saxena 	sc->num_io_throttle_group = sc->facts.max_io_throttle_group;
28802d1d418eSSumit Saxena 	mpi3mr_atomic_set(&sc->pend_large_data_sz, 0);
28812d1d418eSSumit Saxena 
28822d1d418eSSumit Saxena 	if (init_type == MPI3MR_INIT_TYPE_RESET) {
28832d1d418eSSumit Saxena 		retval = mpi3mr_validate_fw_update(sc);
28842d1d418eSSumit Saxena 		if (retval)
28852d1d418eSSumit Saxena 			goto out_failed;
28862d1d418eSSumit Saxena 	} else {
28872d1d418eSSumit Saxena 		sc->reply_sz = sc->facts.reply_sz;
28882d1d418eSSumit Saxena 	}
28892d1d418eSSumit Saxena 
28902d1d418eSSumit Saxena 	mpi3mr_display_ioc_info(sc);
28912d1d418eSSumit Saxena 
28922d1d418eSSumit Saxena 	retval = mpi3mr_reply_alloc(sc);
28932d1d418eSSumit Saxena 	if (retval) {
28942d1d418eSSumit Saxena 		mpi3mr_dprint(sc, MPI3MR_ERROR, "Failed to allocated reply and sense buffers, retval: 0x%x\n",
28952d1d418eSSumit Saxena 		    retval);
28962d1d418eSSumit Saxena 		goto out_failed;
28972d1d418eSSumit Saxena 	}
28982d1d418eSSumit Saxena 
28992d1d418eSSumit Saxena 	if (init_type == MPI3MR_INIT_TYPE_INIT) {
29002d1d418eSSumit Saxena 		retval = mpi3mr_alloc_chain_bufs(sc);
29012d1d418eSSumit Saxena 		if (retval) {
29022d1d418eSSumit Saxena 			mpi3mr_dprint(sc, MPI3MR_ERROR, "Failed to allocated chain buffers, retval: 0x%x\n",
29032d1d418eSSumit Saxena 			    retval);
29042d1d418eSSumit Saxena 			goto out_failed;
29052d1d418eSSumit Saxena 		}
29062d1d418eSSumit Saxena 	}
29072d1d418eSSumit Saxena 
29082d1d418eSSumit Saxena 	retval = mpi3mr_issue_iocinit(sc);
29092d1d418eSSumit Saxena 	if (retval) {
29102d1d418eSSumit Saxena 		mpi3mr_dprint(sc, MPI3MR_ERROR, "Failed to Issue IOC Init, retval: 0x%x\n",
29112d1d418eSSumit Saxena 		    retval);
29122d1d418eSSumit Saxena 		goto out_failed;
29132d1d418eSSumit Saxena 	}
29142d1d418eSSumit Saxena 
29152d1d418eSSumit Saxena 	mpi3mr_print_fw_pkg_ver(sc);
29162d1d418eSSumit Saxena 
29172d1d418eSSumit Saxena 	sc->reply_free_q_host_index = sc->num_reply_bufs;
29182d1d418eSSumit Saxena 	mpi3mr_regwrite(sc, MPI3_SYSIF_REPLY_FREE_HOST_INDEX_OFFSET,
29192d1d418eSSumit Saxena 		sc->reply_free_q_host_index);
29202d1d418eSSumit Saxena 
29212d1d418eSSumit Saxena 	sc->sense_buf_q_host_index = sc->num_sense_bufs;
29222d1d418eSSumit Saxena 
29232d1d418eSSumit Saxena 	mpi3mr_regwrite(sc, MPI3_SYSIF_SENSE_BUF_FREE_HOST_INDEX_OFFSET,
29242d1d418eSSumit Saxena 		sc->sense_buf_q_host_index);
29252d1d418eSSumit Saxena 
29262d1d418eSSumit Saxena 	if (init_type == MPI3MR_INIT_TYPE_INIT) {
29272d1d418eSSumit Saxena 		retval = mpi3mr_alloc_interrupts(sc, 0);
29282d1d418eSSumit Saxena 		if (retval) {
29292d1d418eSSumit Saxena 			mpi3mr_dprint(sc, MPI3MR_ERROR, "Failed to allocate interrupts, retval: 0x%x\n",
29302d1d418eSSumit Saxena 			    retval);
29312d1d418eSSumit Saxena 			goto out_failed;
29322d1d418eSSumit Saxena 		}
29332d1d418eSSumit Saxena 
29342d1d418eSSumit Saxena 		retval = mpi3mr_setup_irqs(sc);
29352d1d418eSSumit Saxena 		if (retval) {
29362d1d418eSSumit Saxena 			printf(IOCNAME "Failed to setup ISR, error: 0x%x\n",
29372d1d418eSSumit Saxena 			    sc->name, retval);
29382d1d418eSSumit Saxena 			goto out_failed;
29392d1d418eSSumit Saxena 		}
29402d1d418eSSumit Saxena 
29412d1d418eSSumit Saxena 		mpi3mr_enable_interrupts(sc);
29422d1d418eSSumit Saxena 
29432d1d418eSSumit Saxena 	} else
29442d1d418eSSumit Saxena 		mpi3mr_enable_interrupts(sc);
29452d1d418eSSumit Saxena 
29462d1d418eSSumit Saxena 	retval = mpi3mr_create_op_queues(sc);
29472d1d418eSSumit Saxena 
29482d1d418eSSumit Saxena 	if (retval) {
29492d1d418eSSumit Saxena 		mpi3mr_dprint(sc, MPI3MR_ERROR, "Failed to create operational queues, error: %d\n",
29502d1d418eSSumit Saxena 		    retval);
29512d1d418eSSumit Saxena 		goto out_failed;
29522d1d418eSSumit Saxena 	}
29532d1d418eSSumit Saxena 
29542d1d418eSSumit Saxena 	if (!sc->throttle_groups && sc->num_io_throttle_group) {
29552d1d418eSSumit Saxena 		mpi3mr_dprint(sc, MPI3MR_ERROR, "allocating memory for throttle groups\n");
29562d1d418eSSumit Saxena 		size = sizeof(struct mpi3mr_throttle_group_info);
29572d1d418eSSumit Saxena 		sc->throttle_groups = (struct mpi3mr_throttle_group_info *)
29582d1d418eSSumit Saxena 					  malloc(sc->num_io_throttle_group *
29592d1d418eSSumit Saxena 					      size, M_MPI3MR, M_NOWAIT | M_ZERO);
29602d1d418eSSumit Saxena 		if (!sc->throttle_groups)
29612d1d418eSSumit Saxena 			goto out_failed;
29622d1d418eSSumit Saxena 	}
29632d1d418eSSumit Saxena 
29642d1d418eSSumit Saxena 	if (init_type == MPI3MR_INIT_TYPE_RESET) {
29652d1d418eSSumit Saxena 		mpi3mr_dprint(sc, MPI3MR_INFO, "Re-register events\n");
29662d1d418eSSumit Saxena 		retval = mpi3mr_register_events(sc);
29672d1d418eSSumit Saxena 		if (retval) {
29682d1d418eSSumit Saxena 			mpi3mr_dprint(sc, MPI3MR_INFO, "Failed to re-register events, retval: 0x%x\n",
29692d1d418eSSumit Saxena 			    retval);
29702d1d418eSSumit Saxena 			goto out_failed;
29712d1d418eSSumit Saxena 		}
29722d1d418eSSumit Saxena 
29732d1d418eSSumit Saxena 		mpi3mr_dprint(sc, MPI3MR_INFO, "Issuing Port Enable\n");
29742d1d418eSSumit Saxena 		retval = mpi3mr_issue_port_enable(sc, 0);
29752d1d418eSSumit Saxena 		if (retval) {
29762d1d418eSSumit Saxena 			mpi3mr_dprint(sc, MPI3MR_INFO, "Failed to issue port enable, retval: 0x%x\n",
29772d1d418eSSumit Saxena 			    retval);
29782d1d418eSSumit Saxena 			goto out_failed;
29792d1d418eSSumit Saxena 		}
29802d1d418eSSumit Saxena 	}
29812d1d418eSSumit Saxena 	retval = mpi3mr_pel_alloc(sc);
29822d1d418eSSumit Saxena 	if (retval) {
29832d1d418eSSumit Saxena 		mpi3mr_dprint(sc, MPI3MR_ERROR, "Failed to allocate memory for PEL, retval: 0x%x\n",
29842d1d418eSSumit Saxena 		    retval);
29852d1d418eSSumit Saxena 		goto out_failed;
29862d1d418eSSumit Saxena 	}
29872d1d418eSSumit Saxena 
29882d1d418eSSumit Saxena 	return retval;
29892d1d418eSSumit Saxena 
29902d1d418eSSumit Saxena out_failed:
29912d1d418eSSumit Saxena 	retval = -1;
29922d1d418eSSumit Saxena 	return retval;
29932d1d418eSSumit Saxena }
29942d1d418eSSumit Saxena 
mpi3mr_port_enable_complete(struct mpi3mr_softc * sc,struct mpi3mr_drvr_cmd * drvrcmd)29952d1d418eSSumit Saxena static void mpi3mr_port_enable_complete(struct mpi3mr_softc *sc,
29962d1d418eSSumit Saxena     struct mpi3mr_drvr_cmd *drvrcmd)
29972d1d418eSSumit Saxena {
29982d1d418eSSumit Saxena 	drvrcmd->state = MPI3MR_CMD_NOTUSED;
29992d1d418eSSumit Saxena 	drvrcmd->callback = NULL;
30002d1d418eSSumit Saxena 	printf(IOCNAME "Completing Port Enable Request\n", sc->name);
30012d1d418eSSumit Saxena 	sc->mpi3mr_flags |= MPI3MR_FLAGS_PORT_ENABLE_DONE;
30022d1d418eSSumit Saxena 	mpi3mr_startup_decrement(sc->cam_sc);
30032d1d418eSSumit Saxena }
30042d1d418eSSumit Saxena 
mpi3mr_issue_port_enable(struct mpi3mr_softc * sc,U8 async)30052d1d418eSSumit Saxena int mpi3mr_issue_port_enable(struct mpi3mr_softc *sc, U8 async)
30062d1d418eSSumit Saxena {
30072d1d418eSSumit Saxena 	Mpi3PortEnableRequest_t pe_req;
30082d1d418eSSumit Saxena 	int retval = 0;
30092d1d418eSSumit Saxena 
30102d1d418eSSumit Saxena 	memset(&pe_req, 0, sizeof(pe_req));
30112d1d418eSSumit Saxena 	mtx_lock(&sc->init_cmds.completion.lock);
30122d1d418eSSumit Saxena 	if (sc->init_cmds.state & MPI3MR_CMD_PENDING) {
30132d1d418eSSumit Saxena 		retval = -1;
30142d1d418eSSumit Saxena 		printf(IOCNAME "Issue PortEnable: Init command is in use\n", sc->name);
30152d1d418eSSumit Saxena 		mtx_unlock(&sc->init_cmds.completion.lock);
30162d1d418eSSumit Saxena 		goto out;
30172d1d418eSSumit Saxena 	}
30182d1d418eSSumit Saxena 
30192d1d418eSSumit Saxena 	sc->init_cmds.state = MPI3MR_CMD_PENDING;
30202d1d418eSSumit Saxena 
30212d1d418eSSumit Saxena 	if (async) {
30222d1d418eSSumit Saxena 		sc->init_cmds.is_waiting = 0;
30232d1d418eSSumit Saxena 		sc->init_cmds.callback = mpi3mr_port_enable_complete;
30242d1d418eSSumit Saxena 	} else {
30252d1d418eSSumit Saxena 		sc->init_cmds.is_waiting = 1;
30262d1d418eSSumit Saxena 		sc->init_cmds.callback = NULL;
30272d1d418eSSumit Saxena 		init_completion(&sc->init_cmds.completion);
30282d1d418eSSumit Saxena 	}
30292d1d418eSSumit Saxena 	pe_req.HostTag = MPI3MR_HOSTTAG_INITCMDS;
30302d1d418eSSumit Saxena 	pe_req.Function = MPI3_FUNCTION_PORT_ENABLE;
30312d1d418eSSumit Saxena 
30322d1d418eSSumit Saxena 	printf(IOCNAME "Sending Port Enable Request\n", sc->name);
30332d1d418eSSumit Saxena 	retval = mpi3mr_submit_admin_cmd(sc, &pe_req, sizeof(pe_req));
30342d1d418eSSumit Saxena 	if (retval) {
30352d1d418eSSumit Saxena 		printf(IOCNAME "Issue PortEnable: Admin Post failed\n",
30362d1d418eSSumit Saxena 		    sc->name);
30372d1d418eSSumit Saxena 		goto out_unlock;
30382d1d418eSSumit Saxena 	}
30392d1d418eSSumit Saxena 
30402d1d418eSSumit Saxena 	if (!async) {
30412d1d418eSSumit Saxena 		wait_for_completion_timeout(&sc->init_cmds.completion,
30422d1d418eSSumit Saxena 		    MPI3MR_PORTENABLE_TIMEOUT);
30432d1d418eSSumit Saxena 		if (!(sc->init_cmds.state & MPI3MR_CMD_COMPLETE)) {
30442d1d418eSSumit Saxena 			printf(IOCNAME "Issue PortEnable: command timed out\n",
30452d1d418eSSumit Saxena 			    sc->name);
30462d1d418eSSumit Saxena 			retval = -1;
30472d1d418eSSumit Saxena 			mpi3mr_check_rh_fault_ioc(sc, MPI3MR_RESET_FROM_PE_TIMEOUT);
30482d1d418eSSumit Saxena 			goto out_unlock;
30492d1d418eSSumit Saxena 		}
30502d1d418eSSumit Saxena 		mpi3mr_port_enable_complete(sc, &sc->init_cmds);
30512d1d418eSSumit Saxena 	}
30522d1d418eSSumit Saxena out_unlock:
30532d1d418eSSumit Saxena 	mtx_unlock(&sc->init_cmds.completion.lock);
30542d1d418eSSumit Saxena 
30552d1d418eSSumit Saxena out:
30562d1d418eSSumit Saxena 	return retval;
30572d1d418eSSumit Saxena }
30582d1d418eSSumit Saxena 
30592d1d418eSSumit Saxena void
mpi3mr_watchdog_thread(void * arg)30602d1d418eSSumit Saxena mpi3mr_watchdog_thread(void *arg)
30612d1d418eSSumit Saxena {
30622d1d418eSSumit Saxena 	struct mpi3mr_softc *sc;
30632d1d418eSSumit Saxena 	enum mpi3mr_iocstate ioc_state;
30642d1d418eSSumit Saxena 	U32 fault, host_diagnostic, ioc_status;
30652d1d418eSSumit Saxena 
30662d1d418eSSumit Saxena 	sc = (struct mpi3mr_softc *)arg;
30672d1d418eSSumit Saxena 
30682d1d418eSSumit Saxena 	mpi3mr_dprint(sc, MPI3MR_XINFO, "%s\n", __func__);
30692d1d418eSSumit Saxena 
30702d1d418eSSumit Saxena 	sc->watchdog_thread_active = 1;
30712d1d418eSSumit Saxena 	mtx_lock(&sc->reset_mutex);
30722d1d418eSSumit Saxena 	for (;;) {
30732d1d418eSSumit Saxena 		if (sc->mpi3mr_flags & MPI3MR_FLAGS_SHUTDOWN ||
30742d1d418eSSumit Saxena 		    (sc->unrecoverable == 1)) {
30752d1d418eSSumit Saxena 			mpi3mr_dprint(sc, MPI3MR_INFO,
30762d1d418eSSumit Saxena 			    "Exit due to %s from %s\n",
30772d1d418eSSumit Saxena 			   sc->mpi3mr_flags & MPI3MR_FLAGS_SHUTDOWN ? "Shutdown" :
30782d1d418eSSumit Saxena 			    "Hardware critical error", __func__);
30792d1d418eSSumit Saxena 			break;
30802d1d418eSSumit Saxena 		}
30817c491309SWarner Losh 		mtx_unlock(&sc->reset_mutex);
30822d1d418eSSumit Saxena 
30832d1d418eSSumit Saxena 		if ((sc->prepare_for_reset) &&
30842d1d418eSSumit Saxena 		    ((sc->prepare_for_reset_timeout_counter++) >=
30852d1d418eSSumit Saxena 		     MPI3MR_PREPARE_FOR_RESET_TIMEOUT)) {
30862d1d418eSSumit Saxena 			mpi3mr_soft_reset_handler(sc,
30872d1d418eSSumit Saxena 			    MPI3MR_RESET_FROM_CIACTVRST_TIMER, 1);
30887c491309SWarner Losh 			goto sleep;
30892d1d418eSSumit Saxena 		}
30902d1d418eSSumit Saxena 
30912d1d418eSSumit Saxena 		ioc_status = mpi3mr_regread(sc, MPI3_SYSIF_IOC_STATUS_OFFSET);
30922d1d418eSSumit Saxena 
30932d1d418eSSumit Saxena 		if (ioc_status & MPI3_SYSIF_IOC_STATUS_RESET_HISTORY) {
30942d1d418eSSumit Saxena 			mpi3mr_soft_reset_handler(sc, MPI3MR_RESET_FROM_FIRMWARE, 0);
30957c491309SWarner Losh 			goto sleep;
30962d1d418eSSumit Saxena 		}
30972d1d418eSSumit Saxena 
30982d1d418eSSumit Saxena 		ioc_state = mpi3mr_get_iocstate(sc);
30992d1d418eSSumit Saxena 		if (ioc_state == MRIOC_STATE_FAULT) {
31002d1d418eSSumit Saxena 			fault = mpi3mr_regread(sc, MPI3_SYSIF_FAULT_OFFSET) &
31012d1d418eSSumit Saxena 			    MPI3_SYSIF_FAULT_CODE_MASK;
31022d1d418eSSumit Saxena 
31032d1d418eSSumit Saxena 			host_diagnostic = mpi3mr_regread(sc, MPI3_SYSIF_HOST_DIAG_OFFSET);
31042d1d418eSSumit Saxena 			if (host_diagnostic & MPI3_SYSIF_HOST_DIAG_SAVE_IN_PROGRESS) {
31052d1d418eSSumit Saxena 				if (!sc->diagsave_timeout) {
31062d1d418eSSumit Saxena 					mpi3mr_print_fault_info(sc);
31072d1d418eSSumit Saxena 					mpi3mr_dprint(sc, MPI3MR_INFO,
31082d1d418eSSumit Saxena 						"diag save in progress\n");
31092d1d418eSSumit Saxena 				}
31102d1d418eSSumit Saxena 				if ((sc->diagsave_timeout++) <= MPI3_SYSIF_DIAG_SAVE_TIMEOUT)
31117c491309SWarner Losh 					goto sleep;
31122d1d418eSSumit Saxena 			}
31132d1d418eSSumit Saxena 			mpi3mr_print_fault_info(sc);
31142d1d418eSSumit Saxena 			sc->diagsave_timeout = 0;
31152d1d418eSSumit Saxena 
31162d1d418eSSumit Saxena 			if ((fault == MPI3_SYSIF_FAULT_CODE_POWER_CYCLE_REQUIRED) ||
31172d1d418eSSumit Saxena 			    (fault == MPI3_SYSIF_FAULT_CODE_COMPLETE_RESET_NEEDED)) {
31182d1d418eSSumit Saxena 				mpi3mr_dprint(sc, MPI3MR_INFO,
31192d1d418eSSumit Saxena 				    "Controller requires system power cycle or complete reset is needed,"
31202d1d418eSSumit Saxena 				    "fault code: 0x%x. marking controller as unrecoverable\n", fault);
31212d1d418eSSumit Saxena 				sc->unrecoverable = 1;
31227c491309SWarner Losh 				break;
31232d1d418eSSumit Saxena 			}
31242d1d418eSSumit Saxena 			if ((fault == MPI3_SYSIF_FAULT_CODE_DIAG_FAULT_RESET)
31252d1d418eSSumit Saxena 			    || (fault == MPI3_SYSIF_FAULT_CODE_SOFT_RESET_IN_PROGRESS)
31262d1d418eSSumit Saxena 			    || (sc->reset_in_progress))
31277c491309SWarner Losh 				break;
31282d1d418eSSumit Saxena 			if (fault == MPI3_SYSIF_FAULT_CODE_CI_ACTIVATION_RESET)
31292d1d418eSSumit Saxena 				mpi3mr_soft_reset_handler(sc,
31302d1d418eSSumit Saxena 				    MPI3MR_RESET_FROM_CIACTIV_FAULT, 0);
31312d1d418eSSumit Saxena 			else
31322d1d418eSSumit Saxena 				mpi3mr_soft_reset_handler(sc,
31332d1d418eSSumit Saxena 				    MPI3MR_RESET_FROM_FAULT_WATCH, 0);
31342d1d418eSSumit Saxena 
31352d1d418eSSumit Saxena 		}
31362d1d418eSSumit Saxena 
31372d1d418eSSumit Saxena 		if (sc->reset.type == MPI3MR_TRIGGER_SOFT_RESET) {
31382d1d418eSSumit Saxena 			mpi3mr_print_fault_info(sc);
31392d1d418eSSumit Saxena 			mpi3mr_soft_reset_handler(sc, sc->reset.reason, 1);
31402d1d418eSSumit Saxena 		}
31417c491309SWarner Losh sleep:
31427c491309SWarner Losh 		mtx_lock(&sc->reset_mutex);
31437c491309SWarner Losh 		/*
31447c491309SWarner Losh 		 * Sleep for 1 second if we're not exiting, then loop to top
31457c491309SWarner Losh 		 * to poll exit status and hardware health.
31467c491309SWarner Losh 		 */
31477c491309SWarner Losh 		if ((sc->mpi3mr_flags & MPI3MR_FLAGS_SHUTDOWN) == 0 &&
31487c491309SWarner Losh 		    !sc->unrecoverable) {
31497c491309SWarner Losh 			msleep(&sc->watchdog_chan, &sc->reset_mutex, PRIBIO,
31507c491309SWarner Losh 			    "mpi3mr_watchdog", 1 * hz);
31512d1d418eSSumit Saxena 		}
31527c491309SWarner Losh 	}
31532d1d418eSSumit Saxena 	mtx_unlock(&sc->reset_mutex);
31542d1d418eSSumit Saxena 	sc->watchdog_thread_active = 0;
31552d1d418eSSumit Saxena 	mpi3mr_kproc_exit(0);
31562d1d418eSSumit Saxena }
31572d1d418eSSumit Saxena 
mpi3mr_display_event_data(struct mpi3mr_softc * sc,Mpi3EventNotificationReply_t * event_rep)31582d1d418eSSumit Saxena static void mpi3mr_display_event_data(struct mpi3mr_softc *sc,
31592d1d418eSSumit Saxena 	Mpi3EventNotificationReply_t *event_rep)
31602d1d418eSSumit Saxena {
31612d1d418eSSumit Saxena 	char *desc = NULL;
31622d1d418eSSumit Saxena 	U16 event;
31632d1d418eSSumit Saxena 
31642d1d418eSSumit Saxena 	event = event_rep->Event;
31652d1d418eSSumit Saxena 
31662d1d418eSSumit Saxena 	switch (event) {
31672d1d418eSSumit Saxena 	case MPI3_EVENT_LOG_DATA:
31682d1d418eSSumit Saxena 		desc = "Log Data";
31692d1d418eSSumit Saxena 		break;
31702d1d418eSSumit Saxena 	case MPI3_EVENT_CHANGE:
31712d1d418eSSumit Saxena 		desc = "Event Change";
31722d1d418eSSumit Saxena 		break;
31732d1d418eSSumit Saxena 	case MPI3_EVENT_GPIO_INTERRUPT:
31742d1d418eSSumit Saxena 		desc = "GPIO Interrupt";
31752d1d418eSSumit Saxena 		break;
31762d1d418eSSumit Saxena 	case MPI3_EVENT_CABLE_MGMT:
31772d1d418eSSumit Saxena 		desc = "Cable Management";
31782d1d418eSSumit Saxena 		break;
31792d1d418eSSumit Saxena 	case MPI3_EVENT_ENERGY_PACK_CHANGE:
31802d1d418eSSumit Saxena 		desc = "Energy Pack Change";
31812d1d418eSSumit Saxena 		break;
31822d1d418eSSumit Saxena 	case MPI3_EVENT_DEVICE_ADDED:
31832d1d418eSSumit Saxena 	{
31842d1d418eSSumit Saxena 		Mpi3DevicePage0_t *event_data =
31852d1d418eSSumit Saxena 		    (Mpi3DevicePage0_t *)event_rep->EventData;
31862d1d418eSSumit Saxena 		mpi3mr_dprint(sc, MPI3MR_EVENT, "Device Added: Dev=0x%04x Form=0x%x Perst id: 0x%x\n",
31872d1d418eSSumit Saxena 			event_data->DevHandle, event_data->DeviceForm, event_data->PersistentID);
31882d1d418eSSumit Saxena 		return;
31892d1d418eSSumit Saxena 	}
31902d1d418eSSumit Saxena 	case MPI3_EVENT_DEVICE_INFO_CHANGED:
31912d1d418eSSumit Saxena 	{
31922d1d418eSSumit Saxena 		Mpi3DevicePage0_t *event_data =
31932d1d418eSSumit Saxena 		    (Mpi3DevicePage0_t *)event_rep->EventData;
31942d1d418eSSumit Saxena 		mpi3mr_dprint(sc, MPI3MR_EVENT, "Device Info Changed: Dev=0x%04x Form=0x%x\n",
31952d1d418eSSumit Saxena 			event_data->DevHandle, event_data->DeviceForm);
31962d1d418eSSumit Saxena 		return;
31972d1d418eSSumit Saxena 	}
31982d1d418eSSumit Saxena 	case MPI3_EVENT_DEVICE_STATUS_CHANGE:
31992d1d418eSSumit Saxena 	{
32002d1d418eSSumit Saxena 		Mpi3EventDataDeviceStatusChange_t *event_data =
32012d1d418eSSumit Saxena 		    (Mpi3EventDataDeviceStatusChange_t *)event_rep->EventData;
32022d1d418eSSumit Saxena 		mpi3mr_dprint(sc, MPI3MR_EVENT, "Device Status Change: Dev=0x%04x RC=0x%x\n",
32032d1d418eSSumit Saxena 			event_data->DevHandle, event_data->ReasonCode);
32042d1d418eSSumit Saxena 		return;
32052d1d418eSSumit Saxena 	}
32062d1d418eSSumit Saxena 	case MPI3_EVENT_SAS_DISCOVERY:
32072d1d418eSSumit Saxena 	{
32082d1d418eSSumit Saxena 		Mpi3EventDataSasDiscovery_t *event_data =
32092d1d418eSSumit Saxena 		    (Mpi3EventDataSasDiscovery_t *)event_rep->EventData;
32102d1d418eSSumit Saxena 		mpi3mr_dprint(sc, MPI3MR_EVENT, "SAS Discovery: (%s)",
32112d1d418eSSumit Saxena 			(event_data->ReasonCode == MPI3_EVENT_SAS_DISC_RC_STARTED) ?
32122d1d418eSSumit Saxena 		    "start" : "stop");
32132d1d418eSSumit Saxena 		if (event_data->DiscoveryStatus &&
32142d1d418eSSumit Saxena 		    (sc->mpi3mr_debug & MPI3MR_EVENT)) {
32152d1d418eSSumit Saxena 			printf("discovery_status(0x%08x)",
32162d1d418eSSumit Saxena 			    event_data->DiscoveryStatus);
32172d1d418eSSumit Saxena 
32182d1d418eSSumit Saxena 		}
32192d1d418eSSumit Saxena 
32202d1d418eSSumit Saxena 		if (sc->mpi3mr_debug & MPI3MR_EVENT)
32212d1d418eSSumit Saxena 			printf("\n");
32222d1d418eSSumit Saxena 		return;
32232d1d418eSSumit Saxena 	}
32242d1d418eSSumit Saxena 	case MPI3_EVENT_SAS_BROADCAST_PRIMITIVE:
32252d1d418eSSumit Saxena 		desc = "SAS Broadcast Primitive";
32262d1d418eSSumit Saxena 		break;
32272d1d418eSSumit Saxena 	case MPI3_EVENT_SAS_NOTIFY_PRIMITIVE:
32282d1d418eSSumit Saxena 		desc = "SAS Notify Primitive";
32292d1d418eSSumit Saxena 		break;
32302d1d418eSSumit Saxena 	case MPI3_EVENT_SAS_INIT_DEVICE_STATUS_CHANGE:
32312d1d418eSSumit Saxena 		desc = "SAS Init Device Status Change";
32322d1d418eSSumit Saxena 		break;
32332d1d418eSSumit Saxena 	case MPI3_EVENT_SAS_INIT_TABLE_OVERFLOW:
32342d1d418eSSumit Saxena 		desc = "SAS Init Table Overflow";
32352d1d418eSSumit Saxena 		break;
32362d1d418eSSumit Saxena 	case MPI3_EVENT_SAS_TOPOLOGY_CHANGE_LIST:
32372d1d418eSSumit Saxena 		desc = "SAS Topology Change List";
32382d1d418eSSumit Saxena 		break;
32392d1d418eSSumit Saxena 	case MPI3_EVENT_ENCL_DEVICE_STATUS_CHANGE:
32402d1d418eSSumit Saxena 		desc = "Enclosure Device Status Change";
32412d1d418eSSumit Saxena 		break;
32422d1d418eSSumit Saxena 	case MPI3_EVENT_HARD_RESET_RECEIVED:
32432d1d418eSSumit Saxena 		desc = "Hard Reset Received";
32442d1d418eSSumit Saxena 		break;
32452d1d418eSSumit Saxena 	case MPI3_EVENT_SAS_PHY_COUNTER:
32462d1d418eSSumit Saxena 		desc = "SAS PHY Counter";
32472d1d418eSSumit Saxena 		break;
32482d1d418eSSumit Saxena 	case MPI3_EVENT_SAS_DEVICE_DISCOVERY_ERROR:
32492d1d418eSSumit Saxena 		desc = "SAS Device Discovery Error";
32502d1d418eSSumit Saxena 		break;
32512d1d418eSSumit Saxena 	case MPI3_EVENT_PCIE_TOPOLOGY_CHANGE_LIST:
32522d1d418eSSumit Saxena 		desc = "PCIE Topology Change List";
32532d1d418eSSumit Saxena 		break;
32542d1d418eSSumit Saxena 	case MPI3_EVENT_PCIE_ENUMERATION:
32552d1d418eSSumit Saxena 	{
32562d1d418eSSumit Saxena 		Mpi3EventDataPcieEnumeration_t *event_data =
32572d1d418eSSumit Saxena 			(Mpi3EventDataPcieEnumeration_t *)event_rep->EventData;
32582d1d418eSSumit Saxena 		mpi3mr_dprint(sc, MPI3MR_EVENT, "PCIE Enumeration: (%s)",
32592d1d418eSSumit Saxena 			(event_data->ReasonCode ==
32602d1d418eSSumit Saxena 			    MPI3_EVENT_PCIE_ENUM_RC_STARTED) ? "start" :
32612d1d418eSSumit Saxena 			    "stop");
32622d1d418eSSumit Saxena 		if (event_data->EnumerationStatus)
32632d1d418eSSumit Saxena 			mpi3mr_dprint(sc, MPI3MR_EVENT, "enumeration_status(0x%08x)",
32642d1d418eSSumit Saxena 			   event_data->EnumerationStatus);
32652d1d418eSSumit Saxena 		if (sc->mpi3mr_debug & MPI3MR_EVENT)
32662d1d418eSSumit Saxena 			printf("\n");
32672d1d418eSSumit Saxena 		return;
32682d1d418eSSumit Saxena 	}
32692d1d418eSSumit Saxena 	case MPI3_EVENT_PREPARE_FOR_RESET:
32702d1d418eSSumit Saxena 		desc = "Prepare For Reset";
32712d1d418eSSumit Saxena 		break;
32722d1d418eSSumit Saxena 	}
32732d1d418eSSumit Saxena 
32742d1d418eSSumit Saxena 	if (!desc)
32752d1d418eSSumit Saxena 		return;
32762d1d418eSSumit Saxena 
32772d1d418eSSumit Saxena 	mpi3mr_dprint(sc, MPI3MR_EVENT, "%s\n", desc);
32782d1d418eSSumit Saxena }
32792d1d418eSSumit Saxena 
32802d1d418eSSumit Saxena struct mpi3mr_target *
mpi3mr_find_target_by_per_id(struct mpi3mr_cam_softc * cam_sc,uint16_t per_id)32812d1d418eSSumit Saxena mpi3mr_find_target_by_per_id(struct mpi3mr_cam_softc *cam_sc,
32822d1d418eSSumit Saxena     uint16_t per_id)
32832d1d418eSSumit Saxena {
32842d1d418eSSumit Saxena 	struct mpi3mr_target *target = NULL;
32852d1d418eSSumit Saxena 
32862d1d418eSSumit Saxena 	mtx_lock_spin(&cam_sc->sc->target_lock);
32872d1d418eSSumit Saxena 	TAILQ_FOREACH(target, &cam_sc->tgt_list, tgt_next) {
32882d1d418eSSumit Saxena 		if (target->per_id == per_id)
32892d1d418eSSumit Saxena 			break;
32902d1d418eSSumit Saxena 	}
32912d1d418eSSumit Saxena 
32922d1d418eSSumit Saxena 	mtx_unlock_spin(&cam_sc->sc->target_lock);
32932d1d418eSSumit Saxena 	return target;
32942d1d418eSSumit Saxena }
32952d1d418eSSumit Saxena 
32962d1d418eSSumit Saxena struct mpi3mr_target *
mpi3mr_find_target_by_dev_handle(struct mpi3mr_cam_softc * cam_sc,uint16_t handle)32972d1d418eSSumit Saxena mpi3mr_find_target_by_dev_handle(struct mpi3mr_cam_softc *cam_sc,
32982d1d418eSSumit Saxena     uint16_t handle)
32992d1d418eSSumit Saxena {
33002d1d418eSSumit Saxena 	struct mpi3mr_target *target = NULL;
33012d1d418eSSumit Saxena 
33022d1d418eSSumit Saxena 	mtx_lock_spin(&cam_sc->sc->target_lock);
33032d1d418eSSumit Saxena 	TAILQ_FOREACH(target, &cam_sc->tgt_list, tgt_next) {
33042d1d418eSSumit Saxena 		if (target->dev_handle == handle)
33052d1d418eSSumit Saxena 			break;
33062d1d418eSSumit Saxena 
33072d1d418eSSumit Saxena 	}
33082d1d418eSSumit Saxena 	mtx_unlock_spin(&cam_sc->sc->target_lock);
33092d1d418eSSumit Saxena 	return target;
33102d1d418eSSumit Saxena }
33112d1d418eSSumit Saxena 
mpi3mr_update_device(struct mpi3mr_softc * sc,struct mpi3mr_target * tgtdev,Mpi3DevicePage0_t * dev_pg0,bool is_added)33122d1d418eSSumit Saxena void mpi3mr_update_device(struct mpi3mr_softc *sc,
33132d1d418eSSumit Saxena     struct mpi3mr_target *tgtdev, Mpi3DevicePage0_t *dev_pg0,
33142d1d418eSSumit Saxena     bool is_added)
33152d1d418eSSumit Saxena {
33162d1d418eSSumit Saxena 	U16 flags = 0;
33172d1d418eSSumit Saxena 
33182d1d418eSSumit Saxena 	tgtdev->per_id = (dev_pg0->PersistentID);
33192d1d418eSSumit Saxena 	tgtdev->dev_handle = (dev_pg0->DevHandle);
33202d1d418eSSumit Saxena 	tgtdev->dev_type = dev_pg0->DeviceForm;
33212d1d418eSSumit Saxena 	tgtdev->encl_handle = (dev_pg0->EnclosureHandle);
33222d1d418eSSumit Saxena 	tgtdev->parent_handle = (dev_pg0->ParentDevHandle);
33232d1d418eSSumit Saxena 	tgtdev->slot = (dev_pg0->Slot);
33242d1d418eSSumit Saxena 	tgtdev->qdepth = (dev_pg0->QueueDepth);
33252d1d418eSSumit Saxena 	tgtdev->wwid = (dev_pg0->WWID);
33262d1d418eSSumit Saxena 
33272d1d418eSSumit Saxena 	flags = (dev_pg0->Flags);
33282d1d418eSSumit Saxena 	tgtdev->is_hidden = (flags & MPI3_DEVICE0_FLAGS_HIDDEN);
33292d1d418eSSumit Saxena 	if (is_added == true)
33302d1d418eSSumit Saxena 		tgtdev->io_throttle_enabled =
33312d1d418eSSumit Saxena 		    (flags & MPI3_DEVICE0_FLAGS_IO_THROTTLING_REQUIRED) ? 1 : 0;
33322d1d418eSSumit Saxena 
33332d1d418eSSumit Saxena 	switch (dev_pg0->AccessStatus) {
33342d1d418eSSumit Saxena 	case MPI3_DEVICE0_ASTATUS_NO_ERRORS:
33352d1d418eSSumit Saxena 	case MPI3_DEVICE0_ASTATUS_PREPARE:
33362d1d418eSSumit Saxena 	case MPI3_DEVICE0_ASTATUS_NEEDS_INITIALIZATION:
33372d1d418eSSumit Saxena 	case MPI3_DEVICE0_ASTATUS_DEVICE_MISSING_DELAY:
33382d1d418eSSumit Saxena 		break;
33392d1d418eSSumit Saxena 	default:
33402d1d418eSSumit Saxena 		tgtdev->is_hidden = 1;
33412d1d418eSSumit Saxena 		break;
33422d1d418eSSumit Saxena 	}
33432d1d418eSSumit Saxena 
3344*3f3a1554SChandrakanth patil 	switch (flags & MPI3_DEVICE0_FLAGS_MAX_WRITE_SAME_MASK) {
3345*3f3a1554SChandrakanth patil 	case MPI3_DEVICE0_FLAGS_MAX_WRITE_SAME_256_LB:
3346*3f3a1554SChandrakanth patil 		tgtdev->ws_len = 256;
3347*3f3a1554SChandrakanth patil 		break;
3348*3f3a1554SChandrakanth patil 	case MPI3_DEVICE0_FLAGS_MAX_WRITE_SAME_2048_LB:
3349*3f3a1554SChandrakanth patil 		tgtdev->ws_len = 2048;
3350*3f3a1554SChandrakanth patil 		break;
3351*3f3a1554SChandrakanth patil 	case MPI3_DEVICE0_FLAGS_MAX_WRITE_SAME_NO_LIMIT:
3352*3f3a1554SChandrakanth patil 	default:
3353*3f3a1554SChandrakanth patil 		tgtdev->ws_len = 0;
3354*3f3a1554SChandrakanth patil 		break;
3355*3f3a1554SChandrakanth patil 	}
3356*3f3a1554SChandrakanth patil 
33572d1d418eSSumit Saxena 	switch (tgtdev->dev_type) {
33582d1d418eSSumit Saxena 	case MPI3_DEVICE_DEVFORM_SAS_SATA:
33592d1d418eSSumit Saxena 	{
33602d1d418eSSumit Saxena 		Mpi3Device0SasSataFormat_t *sasinf =
33612d1d418eSSumit Saxena 		    &dev_pg0->DeviceSpecific.SasSataFormat;
33622d1d418eSSumit Saxena 		U16 dev_info = (sasinf->DeviceInfo);
33632d1d418eSSumit Saxena 		tgtdev->dev_spec.sassata_inf.dev_info = dev_info;
33642d1d418eSSumit Saxena 		tgtdev->dev_spec.sassata_inf.sas_address =
33652d1d418eSSumit Saxena 		    (sasinf->SASAddress);
33662d1d418eSSumit Saxena 		if ((dev_info & MPI3_SAS_DEVICE_INFO_DEVICE_TYPE_MASK) !=
33672d1d418eSSumit Saxena 		    MPI3_SAS_DEVICE_INFO_DEVICE_TYPE_END_DEVICE)
33682d1d418eSSumit Saxena 			tgtdev->is_hidden = 1;
33692d1d418eSSumit Saxena 		else if (!(dev_info & (MPI3_SAS_DEVICE_INFO_STP_SATA_TARGET |
33702d1d418eSSumit Saxena 			    MPI3_SAS_DEVICE_INFO_SSP_TARGET)))
33712d1d418eSSumit Saxena 			tgtdev->is_hidden = 1;
33722d1d418eSSumit Saxena 		break;
33732d1d418eSSumit Saxena 	}
33742d1d418eSSumit Saxena 	case MPI3_DEVICE_DEVFORM_PCIE:
33752d1d418eSSumit Saxena 	{
33762d1d418eSSumit Saxena 		Mpi3Device0PcieFormat_t *pcieinf =
33772d1d418eSSumit Saxena 		    &dev_pg0->DeviceSpecific.PcieFormat;
33782d1d418eSSumit Saxena 		U16 dev_info = (pcieinf->DeviceInfo);
33792d1d418eSSumit Saxena 
33802d1d418eSSumit Saxena 		tgtdev->q_depth = dev_pg0->QueueDepth;
33812d1d418eSSumit Saxena 		tgtdev->dev_spec.pcie_inf.dev_info = dev_info;
33822d1d418eSSumit Saxena 		tgtdev->dev_spec.pcie_inf.capb =
33832d1d418eSSumit Saxena 		    (pcieinf->Capabilities);
33842d1d418eSSumit Saxena 		tgtdev->dev_spec.pcie_inf.mdts = MPI3MR_DEFAULT_MDTS;
33852d1d418eSSumit Saxena 		if (dev_pg0->AccessStatus == MPI3_DEVICE0_ASTATUS_NO_ERRORS) {
33862d1d418eSSumit Saxena 			tgtdev->dev_spec.pcie_inf.mdts =
33872d1d418eSSumit Saxena 			    (pcieinf->MaximumDataTransferSize);
33882d1d418eSSumit Saxena 			tgtdev->dev_spec.pcie_inf.pgsz = pcieinf->PageSize;
33892d1d418eSSumit Saxena 			tgtdev->dev_spec.pcie_inf.reset_to =
33902d1d418eSSumit Saxena 				pcieinf->ControllerResetTO;
33912d1d418eSSumit Saxena 			tgtdev->dev_spec.pcie_inf.abort_to =
33922d1d418eSSumit Saxena 				pcieinf->NVMeAbortTO;
33932d1d418eSSumit Saxena 		}
33942d1d418eSSumit Saxena 		if (tgtdev->dev_spec.pcie_inf.mdts > (1024 * 1024))
33952d1d418eSSumit Saxena 			tgtdev->dev_spec.pcie_inf.mdts = (1024 * 1024);
33962d1d418eSSumit Saxena 
33972d1d418eSSumit Saxena 		if (((dev_info & MPI3_DEVICE0_PCIE_DEVICE_INFO_TYPE_MASK) !=
33982d1d418eSSumit Saxena 		    MPI3_DEVICE0_PCIE_DEVICE_INFO_TYPE_NVME_DEVICE) &&
33992d1d418eSSumit Saxena 		    ((dev_info & MPI3_DEVICE0_PCIE_DEVICE_INFO_TYPE_MASK) !=
34002d1d418eSSumit Saxena 		    MPI3_DEVICE0_PCIE_DEVICE_INFO_TYPE_SCSI_DEVICE))
34012d1d418eSSumit Saxena 			tgtdev->is_hidden = 1;
34022d1d418eSSumit Saxena 
34032d1d418eSSumit Saxena 		break;
34042d1d418eSSumit Saxena 	}
34052d1d418eSSumit Saxena 	case MPI3_DEVICE_DEVFORM_VD:
34062d1d418eSSumit Saxena 	{
34072d1d418eSSumit Saxena 		Mpi3Device0VdFormat_t *vdinf =
34082d1d418eSSumit Saxena 		    &dev_pg0->DeviceSpecific.VdFormat;
34092d1d418eSSumit Saxena 		struct mpi3mr_throttle_group_info *tg = NULL;
34102d1d418eSSumit Saxena 
34112d1d418eSSumit Saxena 		tgtdev->dev_spec.vol_inf.state = vdinf->VdState;
34122d1d418eSSumit Saxena 		if (vdinf->VdState == MPI3_DEVICE0_VD_STATE_OFFLINE)
34132d1d418eSSumit Saxena 			tgtdev->is_hidden = 1;
34142d1d418eSSumit Saxena 		tgtdev->dev_spec.vol_inf.tg_id = vdinf->IOThrottleGroup;
34152d1d418eSSumit Saxena 		tgtdev->dev_spec.vol_inf.tg_high =
34162d1d418eSSumit Saxena 			vdinf->IOThrottleGroupHigh * 2048;
34172d1d418eSSumit Saxena 		tgtdev->dev_spec.vol_inf.tg_low =
34182d1d418eSSumit Saxena 			vdinf->IOThrottleGroupLow * 2048;
34192d1d418eSSumit Saxena 		if (vdinf->IOThrottleGroup < sc->num_io_throttle_group) {
34202d1d418eSSumit Saxena 			tg = sc->throttle_groups + vdinf->IOThrottleGroup;
34212d1d418eSSumit Saxena 			tg->id = vdinf->IOThrottleGroup;
34222d1d418eSSumit Saxena 			tg->high = tgtdev->dev_spec.vol_inf.tg_high;
34232d1d418eSSumit Saxena 			tg->low = tgtdev->dev_spec.vol_inf.tg_low;
34242d1d418eSSumit Saxena 			if (is_added == true)
34252d1d418eSSumit Saxena 				tg->fw_qd = tgtdev->q_depth;
34262d1d418eSSumit Saxena 			tg->modified_qd = tgtdev->q_depth;
34272d1d418eSSumit Saxena 		}
34282d1d418eSSumit Saxena 		tgtdev->dev_spec.vol_inf.tg = tg;
34292d1d418eSSumit Saxena 		tgtdev->throttle_group = tg;
34302d1d418eSSumit Saxena 		break;
34312d1d418eSSumit Saxena 	}
34322d1d418eSSumit Saxena 	default:
34332d1d418eSSumit Saxena 		goto out;
34342d1d418eSSumit Saxena 	}
34352d1d418eSSumit Saxena 
34362d1d418eSSumit Saxena out:
34372d1d418eSSumit Saxena 	return;
34382d1d418eSSumit Saxena }
34392d1d418eSSumit Saxena 
mpi3mr_create_device(struct mpi3mr_softc * sc,Mpi3DevicePage0_t * dev_pg0)34402d1d418eSSumit Saxena int mpi3mr_create_device(struct mpi3mr_softc *sc,
34412d1d418eSSumit Saxena     Mpi3DevicePage0_t *dev_pg0)
34422d1d418eSSumit Saxena {
34432d1d418eSSumit Saxena 	int retval = 0;
34442d1d418eSSumit Saxena 	struct mpi3mr_target *target = NULL;
34452d1d418eSSumit Saxena 	U16 per_id = 0;
34462d1d418eSSumit Saxena 
34472d1d418eSSumit Saxena 	per_id = dev_pg0->PersistentID;
34482d1d418eSSumit Saxena 
34492d1d418eSSumit Saxena 	mtx_lock_spin(&sc->target_lock);
34502d1d418eSSumit Saxena 	TAILQ_FOREACH(target, &sc->cam_sc->tgt_list, tgt_next) {
34512d1d418eSSumit Saxena 		if (target->per_id == per_id) {
34522d1d418eSSumit Saxena 			target->state = MPI3MR_DEV_CREATED;
34532d1d418eSSumit Saxena 			break;
34542d1d418eSSumit Saxena 		}
34552d1d418eSSumit Saxena 	}
34562d1d418eSSumit Saxena 	mtx_unlock_spin(&sc->target_lock);
34572d1d418eSSumit Saxena 
34582d1d418eSSumit Saxena 	if (target) {
34592d1d418eSSumit Saxena 			mpi3mr_update_device(sc, target, dev_pg0, true);
34602d1d418eSSumit Saxena 	} else {
34612d1d418eSSumit Saxena 			target = malloc(sizeof(*target), M_MPI3MR,
34622d1d418eSSumit Saxena 				 M_NOWAIT | M_ZERO);
34632d1d418eSSumit Saxena 
34642d1d418eSSumit Saxena 			if (target == NULL) {
34652d1d418eSSumit Saxena 				retval = -1;
34662d1d418eSSumit Saxena 				goto out;
34672d1d418eSSumit Saxena 			}
34682d1d418eSSumit Saxena 
34692d1d418eSSumit Saxena 			target->exposed_to_os = 0;
34702d1d418eSSumit Saxena 			mpi3mr_update_device(sc, target, dev_pg0, true);
34712d1d418eSSumit Saxena 			mtx_lock_spin(&sc->target_lock);
34722d1d418eSSumit Saxena 			TAILQ_INSERT_TAIL(&sc->cam_sc->tgt_list, target, tgt_next);
34732d1d418eSSumit Saxena 			target->state = MPI3MR_DEV_CREATED;
34742d1d418eSSumit Saxena 			mtx_unlock_spin(&sc->target_lock);
34752d1d418eSSumit Saxena 	}
34762d1d418eSSumit Saxena out:
34772d1d418eSSumit Saxena 	return retval;
34782d1d418eSSumit Saxena }
34792d1d418eSSumit Saxena 
34802d1d418eSSumit Saxena /**
34812d1d418eSSumit Saxena  * mpi3mr_dev_rmhs_complete_iou - Device removal IOUC completion
34822d1d418eSSumit Saxena  * @sc: Adapter instance reference
34832d1d418eSSumit Saxena  * @drv_cmd: Internal command tracker
34842d1d418eSSumit Saxena  *
34852d1d418eSSumit Saxena  * Issues a target reset TM to the firmware from the device
34862d1d418eSSumit Saxena  * removal TM pend list or retry the removal handshake sequence
34872d1d418eSSumit Saxena  * based on the IOU control request IOC status.
34882d1d418eSSumit Saxena  *
34892d1d418eSSumit Saxena  * Return: Nothing
34902d1d418eSSumit Saxena  */
mpi3mr_dev_rmhs_complete_iou(struct mpi3mr_softc * sc,struct mpi3mr_drvr_cmd * drv_cmd)34912d1d418eSSumit Saxena static void mpi3mr_dev_rmhs_complete_iou(struct mpi3mr_softc *sc,
34922d1d418eSSumit Saxena 	struct mpi3mr_drvr_cmd *drv_cmd)
34932d1d418eSSumit Saxena {
34942d1d418eSSumit Saxena 	U16 cmd_idx = drv_cmd->host_tag - MPI3MR_HOSTTAG_DEVRMCMD_MIN;
34952d1d418eSSumit Saxena 	struct delayed_dev_rmhs_node *delayed_dev_rmhs = NULL;
3496701d776cSChandrakanth patil 	struct mpi3mr_target *tgtdev = NULL;
34972d1d418eSSumit Saxena 
34982d1d418eSSumit Saxena 	mpi3mr_dprint(sc, MPI3MR_EVENT,
34992d1d418eSSumit Saxena 	    "%s :dev_rmhs_iouctrl_complete:handle(0x%04x), ioc_status(0x%04x), loginfo(0x%08x)\n",
35002d1d418eSSumit Saxena 	    __func__, drv_cmd->dev_handle, drv_cmd->ioc_status,
35012d1d418eSSumit Saxena 	    drv_cmd->ioc_loginfo);
35022d1d418eSSumit Saxena 	if (drv_cmd->ioc_status != MPI3_IOCSTATUS_SUCCESS) {
35032d1d418eSSumit Saxena 		if (drv_cmd->retry_count < MPI3MR_DEVRMHS_RETRYCOUNT) {
35042d1d418eSSumit Saxena 			drv_cmd->retry_count++;
35052d1d418eSSumit Saxena 			mpi3mr_dprint(sc, MPI3MR_EVENT,
35062d1d418eSSumit Saxena 			    "%s :dev_rmhs_iouctrl_complete: handle(0x%04x)retrying handshake retry=%d\n",
35072d1d418eSSumit Saxena 			    __func__, drv_cmd->dev_handle,
35082d1d418eSSumit Saxena 			    drv_cmd->retry_count);
35092d1d418eSSumit Saxena 			mpi3mr_dev_rmhs_send_tm(sc, drv_cmd->dev_handle,
35102d1d418eSSumit Saxena 			    drv_cmd, drv_cmd->iou_rc);
35112d1d418eSSumit Saxena 			return;
35122d1d418eSSumit Saxena 		}
35132d1d418eSSumit Saxena 		mpi3mr_dprint(sc, MPI3MR_ERROR,
35142d1d418eSSumit Saxena 		    "%s :dev removal handshake failed after all retries: handle(0x%04x)\n",
35152d1d418eSSumit Saxena 		    __func__, drv_cmd->dev_handle);
35162d1d418eSSumit Saxena 	} else {
3517701d776cSChandrakanth patil 		mtx_lock_spin(&sc->target_lock);
3518701d776cSChandrakanth patil 		TAILQ_FOREACH(tgtdev, &sc->cam_sc->tgt_list, tgt_next) {
3519701d776cSChandrakanth patil 		       if (tgtdev->dev_handle == drv_cmd->dev_handle)
3520701d776cSChandrakanth patil 			       tgtdev->state = MPI3MR_DEV_REMOVE_HS_COMPLETED;
3521701d776cSChandrakanth patil 		}
3522701d776cSChandrakanth patil 		mtx_unlock_spin(&sc->target_lock);
3523701d776cSChandrakanth patil 
35242d1d418eSSumit Saxena 		mpi3mr_dprint(sc, MPI3MR_INFO,
35252d1d418eSSumit Saxena 		    "%s :dev removal handshake completed successfully: handle(0x%04x)\n",
35262d1d418eSSumit Saxena 		    __func__, drv_cmd->dev_handle);
35272d1d418eSSumit Saxena 		mpi3mr_clear_bit(drv_cmd->dev_handle, sc->removepend_bitmap);
35282d1d418eSSumit Saxena 	}
35292d1d418eSSumit Saxena 
35302d1d418eSSumit Saxena 	if (!TAILQ_EMPTY(&sc->delayed_rmhs_list)) {
35312d1d418eSSumit Saxena 		delayed_dev_rmhs = TAILQ_FIRST(&sc->delayed_rmhs_list);
35322d1d418eSSumit Saxena 		drv_cmd->dev_handle = delayed_dev_rmhs->handle;
35332d1d418eSSumit Saxena 		drv_cmd->retry_count = 0;
35342d1d418eSSumit Saxena 		drv_cmd->iou_rc = delayed_dev_rmhs->iou_rc;
35352d1d418eSSumit Saxena 		mpi3mr_dprint(sc, MPI3MR_EVENT,
35362d1d418eSSumit Saxena 		    "%s :dev_rmhs_iouctrl_complete: processing delayed TM: handle(0x%04x)\n",
35372d1d418eSSumit Saxena 		    __func__, drv_cmd->dev_handle);
35382d1d418eSSumit Saxena 		mpi3mr_dev_rmhs_send_tm(sc, drv_cmd->dev_handle, drv_cmd,
35392d1d418eSSumit Saxena 		    drv_cmd->iou_rc);
35402d1d418eSSumit Saxena 		TAILQ_REMOVE(&sc->delayed_rmhs_list, delayed_dev_rmhs, list);
35412d1d418eSSumit Saxena 		free(delayed_dev_rmhs, M_MPI3MR);
35422d1d418eSSumit Saxena 		return;
35432d1d418eSSumit Saxena 	}
35442d1d418eSSumit Saxena 	drv_cmd->state = MPI3MR_CMD_NOTUSED;
35452d1d418eSSumit Saxena 	drv_cmd->callback = NULL;
35462d1d418eSSumit Saxena 	drv_cmd->retry_count = 0;
35472d1d418eSSumit Saxena 	drv_cmd->dev_handle = MPI3MR_INVALID_DEV_HANDLE;
35482d1d418eSSumit Saxena 	mpi3mr_clear_bit(cmd_idx, sc->devrem_bitmap);
35492d1d418eSSumit Saxena }
35502d1d418eSSumit Saxena 
35512d1d418eSSumit Saxena /**
35522d1d418eSSumit Saxena  * mpi3mr_dev_rmhs_complete_tm - Device removal TM completion
35532d1d418eSSumit Saxena  * @sc: Adapter instance reference
35542d1d418eSSumit Saxena  * @drv_cmd: Internal command tracker
35552d1d418eSSumit Saxena  *
35562d1d418eSSumit Saxena  * Issues a target reset TM to the firmware from the device
35572d1d418eSSumit Saxena  * removal TM pend list or issue IO Unit control request as
35582d1d418eSSumit Saxena  * part of device removal or hidden acknowledgment handshake.
35592d1d418eSSumit Saxena  *
35602d1d418eSSumit Saxena  * Return: Nothing
35612d1d418eSSumit Saxena  */
mpi3mr_dev_rmhs_complete_tm(struct mpi3mr_softc * sc,struct mpi3mr_drvr_cmd * drv_cmd)35622d1d418eSSumit Saxena static void mpi3mr_dev_rmhs_complete_tm(struct mpi3mr_softc *sc,
35632d1d418eSSumit Saxena 	struct mpi3mr_drvr_cmd *drv_cmd)
35642d1d418eSSumit Saxena {
35652d1d418eSSumit Saxena 	Mpi3IoUnitControlRequest_t iou_ctrl;
35662d1d418eSSumit Saxena 	U16 cmd_idx = drv_cmd->host_tag - MPI3MR_HOSTTAG_DEVRMCMD_MIN;
35672d1d418eSSumit Saxena 	Mpi3SCSITaskMgmtReply_t *tm_reply = NULL;
35682d1d418eSSumit Saxena 	int retval;
35692d1d418eSSumit Saxena 
35702d1d418eSSumit Saxena 	if (drv_cmd->state & MPI3MR_CMD_REPLYVALID)
35712d1d418eSSumit Saxena 		tm_reply = (Mpi3SCSITaskMgmtReply_t *)drv_cmd->reply;
35722d1d418eSSumit Saxena 
35732d1d418eSSumit Saxena 	if (tm_reply)
35742d1d418eSSumit Saxena 		printf(IOCNAME
35752d1d418eSSumit Saxena 		    "dev_rmhs_tr_complete:handle(0x%04x), ioc_status(0x%04x), loginfo(0x%08x), term_count(%d)\n",
35762d1d418eSSumit Saxena 		    sc->name, drv_cmd->dev_handle, drv_cmd->ioc_status,
35772d1d418eSSumit Saxena 		    drv_cmd->ioc_loginfo,
35782d1d418eSSumit Saxena 		    le32toh(tm_reply->TerminationCount));
35792d1d418eSSumit Saxena 
35802d1d418eSSumit Saxena 	printf(IOCNAME "Issuing IOU CTL: handle(0x%04x) dev_rmhs idx(%d)\n",
35812d1d418eSSumit Saxena 	    sc->name, drv_cmd->dev_handle, cmd_idx);
35822d1d418eSSumit Saxena 
35832d1d418eSSumit Saxena 	memset(&iou_ctrl, 0, sizeof(iou_ctrl));
35842d1d418eSSumit Saxena 
35852d1d418eSSumit Saxena 	drv_cmd->state = MPI3MR_CMD_PENDING;
35862d1d418eSSumit Saxena 	drv_cmd->is_waiting = 0;
35872d1d418eSSumit Saxena 	drv_cmd->callback = mpi3mr_dev_rmhs_complete_iou;
35882d1d418eSSumit Saxena 	iou_ctrl.Operation = drv_cmd->iou_rc;
35892d1d418eSSumit Saxena 	iou_ctrl.Param16[0] = htole16(drv_cmd->dev_handle);
35902d1d418eSSumit Saxena 	iou_ctrl.HostTag = htole16(drv_cmd->host_tag);
35912d1d418eSSumit Saxena 	iou_ctrl.Function = MPI3_FUNCTION_IO_UNIT_CONTROL;
35922d1d418eSSumit Saxena 
35932d1d418eSSumit Saxena 	retval = mpi3mr_submit_admin_cmd(sc, &iou_ctrl, sizeof(iou_ctrl));
35942d1d418eSSumit Saxena 	if (retval) {
35952d1d418eSSumit Saxena 		printf(IOCNAME "Issue DevRmHsTMIOUCTL: Admin post failed\n",
35962d1d418eSSumit Saxena 		    sc->name);
35972d1d418eSSumit Saxena 		goto out_failed;
35982d1d418eSSumit Saxena 	}
35992d1d418eSSumit Saxena 
36002d1d418eSSumit Saxena 	return;
36012d1d418eSSumit Saxena out_failed:
36022d1d418eSSumit Saxena 	drv_cmd->state = MPI3MR_CMD_NOTUSED;
36032d1d418eSSumit Saxena 	drv_cmd->callback = NULL;
36042d1d418eSSumit Saxena 	drv_cmd->dev_handle = MPI3MR_INVALID_DEV_HANDLE;
36052d1d418eSSumit Saxena 	drv_cmd->retry_count = 0;
36062d1d418eSSumit Saxena 	mpi3mr_clear_bit(cmd_idx, sc->devrem_bitmap);
36072d1d418eSSumit Saxena }
36082d1d418eSSumit Saxena 
36092d1d418eSSumit Saxena /**
36102d1d418eSSumit Saxena  * mpi3mr_dev_rmhs_send_tm - Issue TM for device removal
36112d1d418eSSumit Saxena  * @sc: Adapter instance reference
36122d1d418eSSumit Saxena  * @handle: Device handle
36132d1d418eSSumit Saxena  * @cmdparam: Internal command tracker
36142d1d418eSSumit Saxena  * @iou_rc: IO Unit reason code
36152d1d418eSSumit Saxena  *
36162d1d418eSSumit Saxena  * Issues a target reset TM to the firmware or add it to a pend
36172d1d418eSSumit Saxena  * list as part of device removal or hidden acknowledgment
36182d1d418eSSumit Saxena  * handshake.
36192d1d418eSSumit Saxena  *
36202d1d418eSSumit Saxena  * Return: Nothing
36212d1d418eSSumit Saxena  */
mpi3mr_dev_rmhs_send_tm(struct mpi3mr_softc * sc,U16 handle,struct mpi3mr_drvr_cmd * cmdparam,U8 iou_rc)36222d1d418eSSumit Saxena static void mpi3mr_dev_rmhs_send_tm(struct mpi3mr_softc *sc, U16 handle,
36232d1d418eSSumit Saxena 	struct mpi3mr_drvr_cmd *cmdparam, U8 iou_rc)
36242d1d418eSSumit Saxena {
36252d1d418eSSumit Saxena 	Mpi3SCSITaskMgmtRequest_t tm_req;
36262d1d418eSSumit Saxena 	int retval = 0;
36272d1d418eSSumit Saxena 	U16 cmd_idx = MPI3MR_NUM_DEVRMCMD;
36282d1d418eSSumit Saxena 	U8 retrycount = 5;
36292d1d418eSSumit Saxena 	struct mpi3mr_drvr_cmd *drv_cmd = cmdparam;
36302d1d418eSSumit Saxena 	struct delayed_dev_rmhs_node *delayed_dev_rmhs = NULL;
36312d1d418eSSumit Saxena 
36322d1d418eSSumit Saxena 	if (drv_cmd)
36332d1d418eSSumit Saxena 		goto issue_cmd;
36342d1d418eSSumit Saxena 	do {
36352d1d418eSSumit Saxena 		cmd_idx = mpi3mr_find_first_zero_bit(sc->devrem_bitmap,
36362d1d418eSSumit Saxena 		    MPI3MR_NUM_DEVRMCMD);
36372d1d418eSSumit Saxena 		if (cmd_idx < MPI3MR_NUM_DEVRMCMD) {
36382d1d418eSSumit Saxena 			if (!mpi3mr_test_and_set_bit(cmd_idx, sc->devrem_bitmap))
36392d1d418eSSumit Saxena 				break;
36402d1d418eSSumit Saxena 			cmd_idx = MPI3MR_NUM_DEVRMCMD;
36412d1d418eSSumit Saxena 		}
36422d1d418eSSumit Saxena 	} while (retrycount--);
36432d1d418eSSumit Saxena 
36442d1d418eSSumit Saxena 	if (cmd_idx >= MPI3MR_NUM_DEVRMCMD) {
36452d1d418eSSumit Saxena 		delayed_dev_rmhs = malloc(sizeof(*delayed_dev_rmhs),M_MPI3MR,
36462d1d418eSSumit Saxena 		     M_ZERO|M_NOWAIT);
36472d1d418eSSumit Saxena 
36482d1d418eSSumit Saxena 		if (!delayed_dev_rmhs)
36492d1d418eSSumit Saxena 			return;
36502d1d418eSSumit Saxena 		delayed_dev_rmhs->handle = handle;
36512d1d418eSSumit Saxena 		delayed_dev_rmhs->iou_rc = iou_rc;
36522d1d418eSSumit Saxena 		TAILQ_INSERT_TAIL(&(sc->delayed_rmhs_list), delayed_dev_rmhs, list);
36532d1d418eSSumit Saxena 		mpi3mr_dprint(sc, MPI3MR_EVENT, "%s :DevRmHs: tr:handle(0x%04x) is postponed\n",
36542d1d418eSSumit Saxena 		    __func__, handle);
36552d1d418eSSumit Saxena 
36562d1d418eSSumit Saxena 
36572d1d418eSSumit Saxena 		return;
36582d1d418eSSumit Saxena 	}
36592d1d418eSSumit Saxena 	drv_cmd = &sc->dev_rmhs_cmds[cmd_idx];
36602d1d418eSSumit Saxena 
36612d1d418eSSumit Saxena issue_cmd:
36622d1d418eSSumit Saxena 	cmd_idx = drv_cmd->host_tag - MPI3MR_HOSTTAG_DEVRMCMD_MIN;
36632d1d418eSSumit Saxena 	mpi3mr_dprint(sc, MPI3MR_EVENT,
36642d1d418eSSumit Saxena 	    "%s :Issuing TR TM: for devhandle 0x%04x with dev_rmhs %d\n",
36652d1d418eSSumit Saxena 	    __func__, handle, cmd_idx);
36662d1d418eSSumit Saxena 
36672d1d418eSSumit Saxena 	memset(&tm_req, 0, sizeof(tm_req));
36682d1d418eSSumit Saxena 	if (drv_cmd->state & MPI3MR_CMD_PENDING) {
36692d1d418eSSumit Saxena 		mpi3mr_dprint(sc, MPI3MR_EVENT, "%s :Issue TM: Command is in use\n", __func__);
36702d1d418eSSumit Saxena 		goto out;
36712d1d418eSSumit Saxena 	}
36722d1d418eSSumit Saxena 	drv_cmd->state = MPI3MR_CMD_PENDING;
36732d1d418eSSumit Saxena 	drv_cmd->is_waiting = 0;
36742d1d418eSSumit Saxena 	drv_cmd->callback = mpi3mr_dev_rmhs_complete_tm;
36752d1d418eSSumit Saxena 	drv_cmd->dev_handle = handle;
36762d1d418eSSumit Saxena 	drv_cmd->iou_rc = iou_rc;
36772d1d418eSSumit Saxena 	tm_req.DevHandle = htole16(handle);
36782d1d418eSSumit Saxena 	tm_req.TaskType = MPI3_SCSITASKMGMT_TASKTYPE_TARGET_RESET;
36792d1d418eSSumit Saxena 	tm_req.HostTag = htole16(drv_cmd->host_tag);
36802d1d418eSSumit Saxena 	tm_req.TaskHostTag = htole16(MPI3MR_HOSTTAG_INVALID);
36812d1d418eSSumit Saxena 	tm_req.Function = MPI3_FUNCTION_SCSI_TASK_MGMT;
36822d1d418eSSumit Saxena 
36832d1d418eSSumit Saxena 	mpi3mr_set_bit(handle, sc->removepend_bitmap);
36842d1d418eSSumit Saxena 	retval = mpi3mr_submit_admin_cmd(sc, &tm_req, sizeof(tm_req));
36852d1d418eSSumit Saxena 	if (retval) {
36862d1d418eSSumit Saxena 		mpi3mr_dprint(sc, MPI3MR_ERROR, "%s :Issue DevRmHsTM: Admin Post failed\n",
36872d1d418eSSumit Saxena 		    __func__);
36882d1d418eSSumit Saxena 		goto out_failed;
36892d1d418eSSumit Saxena 	}
36902d1d418eSSumit Saxena out:
36912d1d418eSSumit Saxena 	return;
36922d1d418eSSumit Saxena out_failed:
36932d1d418eSSumit Saxena 	drv_cmd->state = MPI3MR_CMD_NOTUSED;
36942d1d418eSSumit Saxena 	drv_cmd->callback = NULL;
36952d1d418eSSumit Saxena 	drv_cmd->dev_handle = MPI3MR_INVALID_DEV_HANDLE;
36962d1d418eSSumit Saxena 	drv_cmd->retry_count = 0;
36972d1d418eSSumit Saxena 	mpi3mr_clear_bit(cmd_idx, sc->devrem_bitmap);
36982d1d418eSSumit Saxena }
36992d1d418eSSumit Saxena 
37002d1d418eSSumit Saxena /**
37012d1d418eSSumit Saxena  * mpi3mr_complete_evt_ack - Event ack request completion
37022d1d418eSSumit Saxena  * @sc: Adapter instance reference
37032d1d418eSSumit Saxena  * @drv_cmd: Internal command tracker
37042d1d418eSSumit Saxena  *
37052d1d418eSSumit Saxena  * This is the completion handler for non blocking event
37062d1d418eSSumit Saxena  * acknowledgment sent to the firmware and this will issue any
37072d1d418eSSumit Saxena  * pending event acknowledgment request.
37082d1d418eSSumit Saxena  *
37092d1d418eSSumit Saxena  * Return: Nothing
37102d1d418eSSumit Saxena  */
mpi3mr_complete_evt_ack(struct mpi3mr_softc * sc,struct mpi3mr_drvr_cmd * drv_cmd)37112d1d418eSSumit Saxena static void mpi3mr_complete_evt_ack(struct mpi3mr_softc *sc,
37122d1d418eSSumit Saxena 	struct mpi3mr_drvr_cmd *drv_cmd)
37132d1d418eSSumit Saxena {
37142d1d418eSSumit Saxena 	U16 cmd_idx = drv_cmd->host_tag - MPI3MR_HOSTTAG_EVTACKCMD_MIN;
37152d1d418eSSumit Saxena 	struct delayed_evtack_node *delayed_evtack = NULL;
37162d1d418eSSumit Saxena 
37172d1d418eSSumit Saxena 	if (drv_cmd->ioc_status != MPI3_IOCSTATUS_SUCCESS) {
37182d1d418eSSumit Saxena 		mpi3mr_dprint(sc, MPI3MR_EVENT,
37192d1d418eSSumit Saxena 		    "%s: Failed IOCStatus(0x%04x) Loginfo(0x%08x)\n", __func__,
37202d1d418eSSumit Saxena 		    (drv_cmd->ioc_status & MPI3_IOCSTATUS_STATUS_MASK),
37212d1d418eSSumit Saxena 		    drv_cmd->ioc_loginfo);
37222d1d418eSSumit Saxena 	}
37232d1d418eSSumit Saxena 
37242d1d418eSSumit Saxena 	if (!TAILQ_EMPTY(&sc->delayed_evtack_cmds_list)) {
37252d1d418eSSumit Saxena 		delayed_evtack = TAILQ_FIRST(&sc->delayed_evtack_cmds_list);
37262d1d418eSSumit Saxena 		mpi3mr_dprint(sc, MPI3MR_EVENT,
37272d1d418eSSumit Saxena 		    "%s: processing delayed event ack for event %d\n",
37282d1d418eSSumit Saxena 		    __func__, delayed_evtack->event);
37292d1d418eSSumit Saxena 		mpi3mr_send_evt_ack(sc, delayed_evtack->event, drv_cmd,
37302d1d418eSSumit Saxena 		    delayed_evtack->event_ctx);
37312d1d418eSSumit Saxena 		TAILQ_REMOVE(&sc->delayed_evtack_cmds_list, delayed_evtack, list);
37322d1d418eSSumit Saxena 		free(delayed_evtack, M_MPI3MR);
37332d1d418eSSumit Saxena 		return;
37342d1d418eSSumit Saxena 	}
37352d1d418eSSumit Saxena 	drv_cmd->state = MPI3MR_CMD_NOTUSED;
37362d1d418eSSumit Saxena 	drv_cmd->callback = NULL;
37372d1d418eSSumit Saxena 	mpi3mr_clear_bit(cmd_idx, sc->evtack_cmds_bitmap);
37382d1d418eSSumit Saxena }
37392d1d418eSSumit Saxena 
37402d1d418eSSumit Saxena /**
37412d1d418eSSumit Saxena  * mpi3mr_send_evt_ack - Issue event acknwoledgment request
37422d1d418eSSumit Saxena  * @sc: Adapter instance reference
37432d1d418eSSumit Saxena  * @event: MPI3 event id
37442d1d418eSSumit Saxena  * @cmdparam: Internal command tracker
37452d1d418eSSumit Saxena  * @event_ctx: Event context
37462d1d418eSSumit Saxena  *
37472d1d418eSSumit Saxena  * Issues event acknowledgment request to the firmware if there
37482d1d418eSSumit Saxena  * is a free command to send the event ack else it to a pend
37492d1d418eSSumit Saxena  * list so that it will be processed on a completion of a prior
37502d1d418eSSumit Saxena  * event acknowledgment .
37512d1d418eSSumit Saxena  *
37522d1d418eSSumit Saxena  * Return: Nothing
37532d1d418eSSumit Saxena  */
mpi3mr_send_evt_ack(struct mpi3mr_softc * sc,U8 event,struct mpi3mr_drvr_cmd * cmdparam,U32 event_ctx)37542d1d418eSSumit Saxena static void mpi3mr_send_evt_ack(struct mpi3mr_softc *sc, U8 event,
37552d1d418eSSumit Saxena 	struct mpi3mr_drvr_cmd *cmdparam, U32 event_ctx)
37562d1d418eSSumit Saxena {
37572d1d418eSSumit Saxena 	Mpi3EventAckRequest_t evtack_req;
37582d1d418eSSumit Saxena 	int retval = 0;
37592d1d418eSSumit Saxena 	U8 retrycount = 5;
37602d1d418eSSumit Saxena 	U16 cmd_idx = MPI3MR_NUM_EVTACKCMD;
37612d1d418eSSumit Saxena 	struct mpi3mr_drvr_cmd *drv_cmd = cmdparam;
37622d1d418eSSumit Saxena 	struct delayed_evtack_node *delayed_evtack = NULL;
37632d1d418eSSumit Saxena 
37642d1d418eSSumit Saxena 	if (drv_cmd)
37652d1d418eSSumit Saxena 		goto issue_cmd;
37662d1d418eSSumit Saxena 	do {
37672d1d418eSSumit Saxena 		cmd_idx = mpi3mr_find_first_zero_bit(sc->evtack_cmds_bitmap,
37682d1d418eSSumit Saxena 		    MPI3MR_NUM_EVTACKCMD);
37692d1d418eSSumit Saxena 		if (cmd_idx < MPI3MR_NUM_EVTACKCMD) {
37702d1d418eSSumit Saxena 			if (!mpi3mr_test_and_set_bit(cmd_idx,
37712d1d418eSSumit Saxena 			    sc->evtack_cmds_bitmap))
37722d1d418eSSumit Saxena 				break;
37732d1d418eSSumit Saxena 			cmd_idx = MPI3MR_NUM_EVTACKCMD;
37742d1d418eSSumit Saxena 		}
37752d1d418eSSumit Saxena 	} while (retrycount--);
37762d1d418eSSumit Saxena 
37772d1d418eSSumit Saxena 	if (cmd_idx >= MPI3MR_NUM_EVTACKCMD) {
37782d1d418eSSumit Saxena 		delayed_evtack = malloc(sizeof(*delayed_evtack),M_MPI3MR,
37792d1d418eSSumit Saxena 		     M_ZERO | M_NOWAIT);
37802d1d418eSSumit Saxena 		if (!delayed_evtack)
37812d1d418eSSumit Saxena 			return;
37822d1d418eSSumit Saxena 		delayed_evtack->event = event;
37832d1d418eSSumit Saxena 		delayed_evtack->event_ctx = event_ctx;
37842d1d418eSSumit Saxena 		TAILQ_INSERT_TAIL(&(sc->delayed_evtack_cmds_list), delayed_evtack, list);
37852d1d418eSSumit Saxena 		mpi3mr_dprint(sc, MPI3MR_EVENT, "%s : Event ack for event:%d is postponed\n",
37862d1d418eSSumit Saxena 		    __func__, event);
37872d1d418eSSumit Saxena 		return;
37882d1d418eSSumit Saxena 	}
37892d1d418eSSumit Saxena 	drv_cmd = &sc->evtack_cmds[cmd_idx];
37902d1d418eSSumit Saxena 
37912d1d418eSSumit Saxena issue_cmd:
37922d1d418eSSumit Saxena 	cmd_idx = drv_cmd->host_tag - MPI3MR_HOSTTAG_EVTACKCMD_MIN;
37932d1d418eSSumit Saxena 
37942d1d418eSSumit Saxena 	memset(&evtack_req, 0, sizeof(evtack_req));
37952d1d418eSSumit Saxena 	if (drv_cmd->state & MPI3MR_CMD_PENDING) {
37962d1d418eSSumit Saxena 		mpi3mr_dprint(sc, MPI3MR_EVENT, "%s: Command is in use\n", __func__);
37972d1d418eSSumit Saxena 		goto out;
37982d1d418eSSumit Saxena 	}
37992d1d418eSSumit Saxena 	drv_cmd->state = MPI3MR_CMD_PENDING;
38002d1d418eSSumit Saxena 	drv_cmd->is_waiting = 0;
38012d1d418eSSumit Saxena 	drv_cmd->callback = mpi3mr_complete_evt_ack;
38022d1d418eSSumit Saxena 	evtack_req.HostTag = htole16(drv_cmd->host_tag);
38032d1d418eSSumit Saxena 	evtack_req.Function = MPI3_FUNCTION_EVENT_ACK;
38042d1d418eSSumit Saxena 	evtack_req.Event = event;
38052d1d418eSSumit Saxena 	evtack_req.EventContext = htole32(event_ctx);
38062d1d418eSSumit Saxena 	retval = mpi3mr_submit_admin_cmd(sc, &evtack_req,
38072d1d418eSSumit Saxena 	    sizeof(evtack_req));
38082d1d418eSSumit Saxena 
38092d1d418eSSumit Saxena 	if (retval) {
38102d1d418eSSumit Saxena 		mpi3mr_dprint(sc, MPI3MR_ERROR, "%s: Admin Post failed\n", __func__);
38112d1d418eSSumit Saxena 		goto out_failed;
38122d1d418eSSumit Saxena 	}
38132d1d418eSSumit Saxena out:
38142d1d418eSSumit Saxena 	return;
38152d1d418eSSumit Saxena out_failed:
38162d1d418eSSumit Saxena 	drv_cmd->state = MPI3MR_CMD_NOTUSED;
38172d1d418eSSumit Saxena 	drv_cmd->callback = NULL;
38182d1d418eSSumit Saxena 	mpi3mr_clear_bit(cmd_idx, sc->evtack_cmds_bitmap);
38192d1d418eSSumit Saxena }
38202d1d418eSSumit Saxena 
38212d1d418eSSumit Saxena /*
38222d1d418eSSumit Saxena  * mpi3mr_pcietopochg_evt_th - PCIETopologyChange evt tophalf
38232d1d418eSSumit Saxena  * @sc: Adapter instance reference
38242d1d418eSSumit Saxena  * @event_reply: Event data
38252d1d418eSSumit Saxena  *
38262d1d418eSSumit Saxena  * Checks for the reason code and based on that either block I/O
38272d1d418eSSumit Saxena  * to device, or unblock I/O to the device, or start the device
38282d1d418eSSumit Saxena  * removal handshake with reason as remove with the firmware for
38292d1d418eSSumit Saxena  * PCIe devices.
38302d1d418eSSumit Saxena  *
38312d1d418eSSumit Saxena  * Return: Nothing
38322d1d418eSSumit Saxena  */
mpi3mr_pcietopochg_evt_th(struct mpi3mr_softc * sc,Mpi3EventNotificationReply_t * event_reply)38332d1d418eSSumit Saxena static void mpi3mr_pcietopochg_evt_th(struct mpi3mr_softc *sc,
38342d1d418eSSumit Saxena 	Mpi3EventNotificationReply_t *event_reply)
38352d1d418eSSumit Saxena {
38362d1d418eSSumit Saxena 	Mpi3EventDataPcieTopologyChangeList_t *topo_evt =
38372d1d418eSSumit Saxena 	    (Mpi3EventDataPcieTopologyChangeList_t *) event_reply->EventData;
38382d1d418eSSumit Saxena 	int i;
38392d1d418eSSumit Saxena 	U16 handle;
38402d1d418eSSumit Saxena 	U8 reason_code;
38412d1d418eSSumit Saxena 	struct mpi3mr_target *tgtdev = NULL;
38422d1d418eSSumit Saxena 
38432d1d418eSSumit Saxena 	for (i = 0; i < topo_evt->NumEntries; i++) {
38442d1d418eSSumit Saxena 		handle = le16toh(topo_evt->PortEntry[i].AttachedDevHandle);
38452d1d418eSSumit Saxena 		if (!handle)
38462d1d418eSSumit Saxena 			continue;
38472d1d418eSSumit Saxena 		reason_code = topo_evt->PortEntry[i].PortStatus;
38482d1d418eSSumit Saxena 		tgtdev = mpi3mr_find_target_by_dev_handle(sc->cam_sc, handle);
38492d1d418eSSumit Saxena 		switch (reason_code) {
38502d1d418eSSumit Saxena 		case MPI3_EVENT_PCIE_TOPO_PS_NOT_RESPONDING:
38512d1d418eSSumit Saxena 			if (tgtdev) {
38522d1d418eSSumit Saxena 				tgtdev->dev_removed = 1;
38532d1d418eSSumit Saxena 				tgtdev->dev_removedelay = 0;
38542d1d418eSSumit Saxena 				mpi3mr_atomic_set(&tgtdev->block_io, 0);
38552d1d418eSSumit Saxena 			}
38562d1d418eSSumit Saxena 			mpi3mr_dev_rmhs_send_tm(sc, handle, NULL,
38572d1d418eSSumit Saxena 			    MPI3_CTRL_OP_REMOVE_DEVICE);
38582d1d418eSSumit Saxena 			break;
38592d1d418eSSumit Saxena 		case MPI3_EVENT_PCIE_TOPO_PS_DELAY_NOT_RESPONDING:
38602d1d418eSSumit Saxena 			if (tgtdev) {
38612d1d418eSSumit Saxena 				tgtdev->dev_removedelay = 1;
38622d1d418eSSumit Saxena 				mpi3mr_atomic_inc(&tgtdev->block_io);
38632d1d418eSSumit Saxena 			}
38642d1d418eSSumit Saxena 			break;
38652d1d418eSSumit Saxena 		case MPI3_EVENT_PCIE_TOPO_PS_RESPONDING:
38662d1d418eSSumit Saxena 			if (tgtdev &&
38672d1d418eSSumit Saxena 			    tgtdev->dev_removedelay) {
38682d1d418eSSumit Saxena 				tgtdev->dev_removedelay = 0;
38692d1d418eSSumit Saxena 				if (mpi3mr_atomic_read(&tgtdev->block_io) > 0)
38702d1d418eSSumit Saxena 					mpi3mr_atomic_dec(&tgtdev->block_io);
38712d1d418eSSumit Saxena 			}
38722d1d418eSSumit Saxena 			break;
38732d1d418eSSumit Saxena 		case MPI3_EVENT_PCIE_TOPO_PS_PORT_CHANGED:
38742d1d418eSSumit Saxena 		default:
38752d1d418eSSumit Saxena 			break;
38762d1d418eSSumit Saxena 		}
38772d1d418eSSumit Saxena 	}
38782d1d418eSSumit Saxena }
38792d1d418eSSumit Saxena 
38802d1d418eSSumit Saxena /**
38812d1d418eSSumit Saxena  * mpi3mr_sastopochg_evt_th - SASTopologyChange evt tophalf
38822d1d418eSSumit Saxena  * @sc: Adapter instance reference
38832d1d418eSSumit Saxena  * @event_reply: Event data
38842d1d418eSSumit Saxena  *
38852d1d418eSSumit Saxena  * Checks for the reason code and based on that either block I/O
38862d1d418eSSumit Saxena  * to device, or unblock I/O to the device, or start the device
38872d1d418eSSumit Saxena  * removal handshake with reason as remove with the firmware for
38882d1d418eSSumit Saxena  * SAS/SATA devices.
38892d1d418eSSumit Saxena  *
38902d1d418eSSumit Saxena  * Return: Nothing
38912d1d418eSSumit Saxena  */
mpi3mr_sastopochg_evt_th(struct mpi3mr_softc * sc,Mpi3EventNotificationReply_t * event_reply)38922d1d418eSSumit Saxena static void mpi3mr_sastopochg_evt_th(struct mpi3mr_softc *sc,
38932d1d418eSSumit Saxena 	Mpi3EventNotificationReply_t *event_reply)
38942d1d418eSSumit Saxena {
38952d1d418eSSumit Saxena 	Mpi3EventDataSasTopologyChangeList_t *topo_evt =
38962d1d418eSSumit Saxena 	    (Mpi3EventDataSasTopologyChangeList_t *)event_reply->EventData;
38972d1d418eSSumit Saxena 	int i;
38982d1d418eSSumit Saxena 	U16 handle;
38992d1d418eSSumit Saxena 	U8 reason_code;
39002d1d418eSSumit Saxena 	struct mpi3mr_target *tgtdev = NULL;
39012d1d418eSSumit Saxena 
39022d1d418eSSumit Saxena 	for (i = 0; i < topo_evt->NumEntries; i++) {
39032d1d418eSSumit Saxena 		handle = le16toh(topo_evt->PhyEntry[i].AttachedDevHandle);
39042d1d418eSSumit Saxena 		if (!handle)
39052d1d418eSSumit Saxena 			continue;
3906baabb919SChandrakanth patil 		reason_code = topo_evt->PhyEntry[i].PhyStatus &
39072d1d418eSSumit Saxena 		    MPI3_EVENT_SAS_TOPO_PHY_RC_MASK;
39082d1d418eSSumit Saxena 		tgtdev = mpi3mr_find_target_by_dev_handle(sc->cam_sc, handle);
39092d1d418eSSumit Saxena 		switch (reason_code) {
39102d1d418eSSumit Saxena 		case MPI3_EVENT_SAS_TOPO_PHY_RC_TARG_NOT_RESPONDING:
39112d1d418eSSumit Saxena 			if (tgtdev) {
39122d1d418eSSumit Saxena 				tgtdev->dev_removed = 1;
39132d1d418eSSumit Saxena 				tgtdev->dev_removedelay = 0;
39142d1d418eSSumit Saxena 				mpi3mr_atomic_set(&tgtdev->block_io, 0);
39152d1d418eSSumit Saxena 			}
39162d1d418eSSumit Saxena 			mpi3mr_dev_rmhs_send_tm(sc, handle, NULL,
39172d1d418eSSumit Saxena 			    MPI3_CTRL_OP_REMOVE_DEVICE);
39182d1d418eSSumit Saxena 			break;
39192d1d418eSSumit Saxena 		case MPI3_EVENT_SAS_TOPO_PHY_RC_DELAY_NOT_RESPONDING:
39202d1d418eSSumit Saxena 			if (tgtdev) {
39212d1d418eSSumit Saxena 				tgtdev->dev_removedelay = 1;
39222d1d418eSSumit Saxena 				mpi3mr_atomic_inc(&tgtdev->block_io);
39232d1d418eSSumit Saxena 			}
39242d1d418eSSumit Saxena 			break;
39252d1d418eSSumit Saxena 		case MPI3_EVENT_SAS_TOPO_PHY_RC_RESPONDING:
39262d1d418eSSumit Saxena 			if (tgtdev &&
39272d1d418eSSumit Saxena 			    tgtdev->dev_removedelay) {
39282d1d418eSSumit Saxena 				tgtdev->dev_removedelay = 0;
39292d1d418eSSumit Saxena 				if (mpi3mr_atomic_read(&tgtdev->block_io) > 0)
39302d1d418eSSumit Saxena 					mpi3mr_atomic_dec(&tgtdev->block_io);
39312d1d418eSSumit Saxena 			}
39322d1d418eSSumit Saxena 		case MPI3_EVENT_SAS_TOPO_PHY_RC_PHY_CHANGED:
39332d1d418eSSumit Saxena 		default:
39342d1d418eSSumit Saxena 			break;
39352d1d418eSSumit Saxena 		}
39362d1d418eSSumit Saxena 	}
39372d1d418eSSumit Saxena 
39382d1d418eSSumit Saxena }
39392d1d418eSSumit Saxena /**
39402d1d418eSSumit Saxena  * mpi3mr_devstatuschg_evt_th - DeviceStatusChange evt tophalf
39412d1d418eSSumit Saxena  * @sc: Adapter instance reference
39422d1d418eSSumit Saxena  * @event_reply: Event data
39432d1d418eSSumit Saxena  *
39442d1d418eSSumit Saxena  * Checks for the reason code and based on that either block I/O
39452d1d418eSSumit Saxena  * to device, or unblock I/O to the device, or start the device
39462d1d418eSSumit Saxena  * removal handshake with reason as remove/hide acknowledgment
39472d1d418eSSumit Saxena  * with the firmware.
39482d1d418eSSumit Saxena  *
39492d1d418eSSumit Saxena  * Return: Nothing
39502d1d418eSSumit Saxena  */
mpi3mr_devstatuschg_evt_th(struct mpi3mr_softc * sc,Mpi3EventNotificationReply_t * event_reply)39512d1d418eSSumit Saxena static void mpi3mr_devstatuschg_evt_th(struct mpi3mr_softc *sc,
39522d1d418eSSumit Saxena 	Mpi3EventNotificationReply_t *event_reply)
39532d1d418eSSumit Saxena {
39542d1d418eSSumit Saxena 	U16 dev_handle = 0;
39552d1d418eSSumit Saxena 	U8 ublock = 0, block = 0, hide = 0, uhide = 0, delete = 0, remove = 0;
39562d1d418eSSumit Saxena 	struct mpi3mr_target *tgtdev = NULL;
39572d1d418eSSumit Saxena 	Mpi3EventDataDeviceStatusChange_t *evtdata =
39582d1d418eSSumit Saxena 	    (Mpi3EventDataDeviceStatusChange_t *) event_reply->EventData;
39592d1d418eSSumit Saxena 
39602d1d418eSSumit Saxena 	dev_handle = le16toh(evtdata->DevHandle);
39612d1d418eSSumit Saxena 
39622d1d418eSSumit Saxena 	switch (evtdata->ReasonCode) {
39632d1d418eSSumit Saxena 	case MPI3_EVENT_DEV_STAT_RC_INT_DEVICE_RESET_STRT:
39642d1d418eSSumit Saxena 	case MPI3_EVENT_DEV_STAT_RC_INT_IT_NEXUS_RESET_STRT:
39652d1d418eSSumit Saxena 		block = 1;
39662d1d418eSSumit Saxena 		break;
39672d1d418eSSumit Saxena 	case MPI3_EVENT_DEV_STAT_RC_HIDDEN:
39682d1d418eSSumit Saxena 		delete = 1;
39692d1d418eSSumit Saxena 		hide = 1;
39702d1d418eSSumit Saxena 		break;
39712d1d418eSSumit Saxena 	case MPI3_EVENT_DEV_STAT_RC_NOT_HIDDEN:
39722d1d418eSSumit Saxena 		uhide = 1;
39732d1d418eSSumit Saxena 		break;
39742d1d418eSSumit Saxena 	case MPI3_EVENT_DEV_STAT_RC_VD_NOT_RESPONDING:
39752d1d418eSSumit Saxena 		delete = 1;
39762d1d418eSSumit Saxena 		remove = 1;
39772d1d418eSSumit Saxena 		break;
39782d1d418eSSumit Saxena 	case MPI3_EVENT_DEV_STAT_RC_INT_DEVICE_RESET_CMP:
39792d1d418eSSumit Saxena 	case MPI3_EVENT_DEV_STAT_RC_INT_IT_NEXUS_RESET_CMP:
39802d1d418eSSumit Saxena 		ublock = 1;
39812d1d418eSSumit Saxena 		break;
39822d1d418eSSumit Saxena 	default:
39832d1d418eSSumit Saxena 		break;
39842d1d418eSSumit Saxena 	}
39852d1d418eSSumit Saxena 
39862d1d418eSSumit Saxena 	tgtdev = mpi3mr_find_target_by_dev_handle(sc->cam_sc, dev_handle);
39872d1d418eSSumit Saxena 
39882d1d418eSSumit Saxena 	if (!tgtdev) {
39892d1d418eSSumit Saxena 		mpi3mr_dprint(sc, MPI3MR_ERROR, "%s :target with dev_handle:0x%x not found\n",
39902d1d418eSSumit Saxena 		    __func__, dev_handle);
39912d1d418eSSumit Saxena 		return;
39922d1d418eSSumit Saxena 	}
39932d1d418eSSumit Saxena 
39942d1d418eSSumit Saxena 	if (block)
39952d1d418eSSumit Saxena 		mpi3mr_atomic_inc(&tgtdev->block_io);
39962d1d418eSSumit Saxena 
39972d1d418eSSumit Saxena 	if (hide)
39982d1d418eSSumit Saxena 		tgtdev->is_hidden = hide;
39992d1d418eSSumit Saxena 
40002d1d418eSSumit Saxena 	if (uhide) {
40012d1d418eSSumit Saxena 		tgtdev->is_hidden = 0;
40022d1d418eSSumit Saxena 		tgtdev->dev_removed = 0;
40032d1d418eSSumit Saxena 	}
40042d1d418eSSumit Saxena 
40052d1d418eSSumit Saxena 	if (delete)
40062d1d418eSSumit Saxena 		tgtdev->dev_removed = 1;
40072d1d418eSSumit Saxena 
40082d1d418eSSumit Saxena 	if (ublock) {
40092d1d418eSSumit Saxena 		if (mpi3mr_atomic_read(&tgtdev->block_io) > 0)
40102d1d418eSSumit Saxena 			mpi3mr_atomic_dec(&tgtdev->block_io);
40112d1d418eSSumit Saxena 	}
40122d1d418eSSumit Saxena 
40132d1d418eSSumit Saxena 	if (remove) {
40142d1d418eSSumit Saxena 		mpi3mr_dev_rmhs_send_tm(sc, dev_handle, NULL,
40152d1d418eSSumit Saxena 					MPI3_CTRL_OP_REMOVE_DEVICE);
40162d1d418eSSumit Saxena 	}
40172d1d418eSSumit Saxena 	if (hide)
40182d1d418eSSumit Saxena 		mpi3mr_dev_rmhs_send_tm(sc, dev_handle, NULL,
40192d1d418eSSumit Saxena 					MPI3_CTRL_OP_HIDDEN_ACK);
40202d1d418eSSumit Saxena }
40212d1d418eSSumit Saxena 
40222d1d418eSSumit Saxena /**
40232d1d418eSSumit Saxena  * mpi3mr_preparereset_evt_th - Prepareforreset evt tophalf
40242d1d418eSSumit Saxena  * @sc: Adapter instance reference
40252d1d418eSSumit Saxena  * @event_reply: Event data
40262d1d418eSSumit Saxena  *
40272d1d418eSSumit Saxena  * Blocks and unblocks host level I/O based on the reason code
40282d1d418eSSumit Saxena  *
40292d1d418eSSumit Saxena  * Return: Nothing
40302d1d418eSSumit Saxena  */
mpi3mr_preparereset_evt_th(struct mpi3mr_softc * sc,Mpi3EventNotificationReply_t * event_reply)40312d1d418eSSumit Saxena static void mpi3mr_preparereset_evt_th(struct mpi3mr_softc *sc,
40322d1d418eSSumit Saxena 	Mpi3EventNotificationReply_t *event_reply)
40332d1d418eSSumit Saxena {
40342d1d418eSSumit Saxena 	Mpi3EventDataPrepareForReset_t *evtdata =
40352d1d418eSSumit Saxena 	    (Mpi3EventDataPrepareForReset_t *)event_reply->EventData;
40362d1d418eSSumit Saxena 
40372d1d418eSSumit Saxena 	if (evtdata->ReasonCode == MPI3_EVENT_PREPARE_RESET_RC_START) {
40382d1d418eSSumit Saxena 		mpi3mr_dprint(sc, MPI3MR_EVENT, "%s :Recieved PrepForReset Event with RC=START\n",
40392d1d418eSSumit Saxena 		    __func__);
40402d1d418eSSumit Saxena 		if (sc->prepare_for_reset)
40412d1d418eSSumit Saxena 			return;
40422d1d418eSSumit Saxena 		sc->prepare_for_reset = 1;
40432d1d418eSSumit Saxena 		sc->prepare_for_reset_timeout_counter = 0;
40442d1d418eSSumit Saxena 	} else if (evtdata->ReasonCode == MPI3_EVENT_PREPARE_RESET_RC_ABORT) {
40452d1d418eSSumit Saxena 		mpi3mr_dprint(sc, MPI3MR_EVENT, "%s :Recieved PrepForReset Event with RC=ABORT\n",
40462d1d418eSSumit Saxena 		    __func__);
40472d1d418eSSumit Saxena 		sc->prepare_for_reset = 0;
40482d1d418eSSumit Saxena 		sc->prepare_for_reset_timeout_counter = 0;
40492d1d418eSSumit Saxena 	}
40502d1d418eSSumit Saxena 	if ((event_reply->MsgFlags & MPI3_EVENT_NOTIFY_MSGFLAGS_ACK_MASK)
40512d1d418eSSumit Saxena 	    == MPI3_EVENT_NOTIFY_MSGFLAGS_ACK_REQUIRED)
40522d1d418eSSumit Saxena 		mpi3mr_send_evt_ack(sc, event_reply->Event, NULL,
40532d1d418eSSumit Saxena 		    le32toh(event_reply->EventContext));
40542d1d418eSSumit Saxena }
40552d1d418eSSumit Saxena 
40562d1d418eSSumit Saxena /**
40572d1d418eSSumit Saxena  * mpi3mr_energypackchg_evt_th - Energypackchange evt tophalf
40582d1d418eSSumit Saxena  * @sc: Adapter instance reference
40592d1d418eSSumit Saxena  * @event_reply: Event data
40602d1d418eSSumit Saxena  *
40612d1d418eSSumit Saxena  * Identifies the new shutdown timeout value and update.
40622d1d418eSSumit Saxena  *
40632d1d418eSSumit Saxena  * Return: Nothing
40642d1d418eSSumit Saxena  */
mpi3mr_energypackchg_evt_th(struct mpi3mr_softc * sc,Mpi3EventNotificationReply_t * event_reply)40652d1d418eSSumit Saxena static void mpi3mr_energypackchg_evt_th(struct mpi3mr_softc *sc,
40662d1d418eSSumit Saxena 	Mpi3EventNotificationReply_t *event_reply)
40672d1d418eSSumit Saxena {
40682d1d418eSSumit Saxena 	Mpi3EventDataEnergyPackChange_t *evtdata =
40692d1d418eSSumit Saxena 	    (Mpi3EventDataEnergyPackChange_t *)event_reply->EventData;
40702d1d418eSSumit Saxena 	U16 shutdown_timeout = le16toh(evtdata->ShutdownTimeout);
40712d1d418eSSumit Saxena 
40722d1d418eSSumit Saxena 	if (shutdown_timeout <= 0) {
40732d1d418eSSumit Saxena 		mpi3mr_dprint(sc, MPI3MR_ERROR,
40742d1d418eSSumit Saxena 		    "%s :Invalid Shutdown Timeout received = %d\n",
40752d1d418eSSumit Saxena 		    __func__, shutdown_timeout);
40762d1d418eSSumit Saxena 		return;
40772d1d418eSSumit Saxena 	}
40782d1d418eSSumit Saxena 
40792d1d418eSSumit Saxena 	mpi3mr_dprint(sc, MPI3MR_EVENT,
40802d1d418eSSumit Saxena 	    "%s :Previous Shutdown Timeout Value = %d New Shutdown Timeout Value = %d\n",
40812d1d418eSSumit Saxena 	    __func__, sc->facts.shutdown_timeout, shutdown_timeout);
40822d1d418eSSumit Saxena 	sc->facts.shutdown_timeout = shutdown_timeout;
40832d1d418eSSumit Saxena }
40842d1d418eSSumit Saxena 
40852d1d418eSSumit Saxena /**
40862d1d418eSSumit Saxena  * mpi3mr_cablemgmt_evt_th - Cable mgmt evt tophalf
40872d1d418eSSumit Saxena  * @sc: Adapter instance reference
40882d1d418eSSumit Saxena  * @event_reply: Event data
40892d1d418eSSumit Saxena  *
40902d1d418eSSumit Saxena  * Displays Cable manegemt event details.
40912d1d418eSSumit Saxena  *
40922d1d418eSSumit Saxena  * Return: Nothing
40932d1d418eSSumit Saxena  */
mpi3mr_cablemgmt_evt_th(struct mpi3mr_softc * sc,Mpi3EventNotificationReply_t * event_reply)40942d1d418eSSumit Saxena static void mpi3mr_cablemgmt_evt_th(struct mpi3mr_softc *sc,
40952d1d418eSSumit Saxena 	Mpi3EventNotificationReply_t *event_reply)
40962d1d418eSSumit Saxena {
40972d1d418eSSumit Saxena 	Mpi3EventDataCableManagement_t *evtdata =
40982d1d418eSSumit Saxena 	    (Mpi3EventDataCableManagement_t *)event_reply->EventData;
40992d1d418eSSumit Saxena 
41002d1d418eSSumit Saxena 	switch (evtdata->Status) {
41012d1d418eSSumit Saxena 	case MPI3_EVENT_CABLE_MGMT_STATUS_INSUFFICIENT_POWER:
41022d1d418eSSumit Saxena 	{
41032d1d418eSSumit Saxena 		mpi3mr_dprint(sc, MPI3MR_INFO, "An active cable with ReceptacleID %d cannot be powered.\n"
41042d1d418eSSumit Saxena 		    "Devices connected to this cable are not detected.\n"
41052d1d418eSSumit Saxena 		    "This cable requires %d mW of power.\n",
41062d1d418eSSumit Saxena 		    evtdata->ReceptacleID,
41072d1d418eSSumit Saxena 		    le32toh(evtdata->ActiveCablePowerRequirement));
41082d1d418eSSumit Saxena 		break;
41092d1d418eSSumit Saxena 	}
41102d1d418eSSumit Saxena 	case MPI3_EVENT_CABLE_MGMT_STATUS_DEGRADED:
41112d1d418eSSumit Saxena 	{
41122d1d418eSSumit Saxena 		mpi3mr_dprint(sc, MPI3MR_INFO, "A cable with ReceptacleID %d is not running at optimal speed\n",
41132d1d418eSSumit Saxena 		    evtdata->ReceptacleID);
41142d1d418eSSumit Saxena 		break;
41152d1d418eSSumit Saxena 	}
41162d1d418eSSumit Saxena 	default:
41172d1d418eSSumit Saxena 		break;
41182d1d418eSSumit Saxena 	}
41192d1d418eSSumit Saxena }
41202d1d418eSSumit Saxena 
41212d1d418eSSumit Saxena /**
41222d1d418eSSumit Saxena  * mpi3mr_process_events - Event's toph-half handler
41232d1d418eSSumit Saxena  * @sc: Adapter instance reference
41242d1d418eSSumit Saxena  * @event_reply: Event data
41252d1d418eSSumit Saxena  *
41262d1d418eSSumit Saxena  * Top half of event processing.
41272d1d418eSSumit Saxena  *
41282d1d418eSSumit Saxena  * Return: Nothing
41292d1d418eSSumit Saxena  */
mpi3mr_process_events(struct mpi3mr_softc * sc,uintptr_t data,Mpi3EventNotificationReply_t * event_reply)41302d1d418eSSumit Saxena static void mpi3mr_process_events(struct mpi3mr_softc *sc,
41312d1d418eSSumit Saxena     uintptr_t data, Mpi3EventNotificationReply_t *event_reply)
41322d1d418eSSumit Saxena {
41332d1d418eSSumit Saxena 	U16 evt_type;
41342d1d418eSSumit Saxena 	bool ack_req = 0, process_evt_bh = 0;
41352d1d418eSSumit Saxena 	struct mpi3mr_fw_event_work *fw_event;
41362d1d418eSSumit Saxena 	U16 sz;
41372d1d418eSSumit Saxena 
41382d1d418eSSumit Saxena 	if (sc->mpi3mr_flags & MPI3MR_FLAGS_SHUTDOWN)
41392d1d418eSSumit Saxena 		goto out;
41402d1d418eSSumit Saxena 
41412d1d418eSSumit Saxena 	if ((event_reply->MsgFlags & MPI3_EVENT_NOTIFY_MSGFLAGS_ACK_MASK)
41422d1d418eSSumit Saxena 	    == MPI3_EVENT_NOTIFY_MSGFLAGS_ACK_REQUIRED)
41432d1d418eSSumit Saxena 		ack_req = 1;
41442d1d418eSSumit Saxena 
41452d1d418eSSumit Saxena 	evt_type = event_reply->Event;
41462d1d418eSSumit Saxena 
41472d1d418eSSumit Saxena 	switch (evt_type) {
41482d1d418eSSumit Saxena 	case MPI3_EVENT_DEVICE_ADDED:
41492d1d418eSSumit Saxena 	{
41502d1d418eSSumit Saxena 		Mpi3DevicePage0_t *dev_pg0 =
41512d1d418eSSumit Saxena 			(Mpi3DevicePage0_t *) event_reply->EventData;
41522d1d418eSSumit Saxena 		if (mpi3mr_create_device(sc, dev_pg0))
41532d1d418eSSumit Saxena 			mpi3mr_dprint(sc, MPI3MR_ERROR,
41542d1d418eSSumit Saxena 			"%s :Failed to add device in the device add event\n",
41552d1d418eSSumit Saxena 			__func__);
41562d1d418eSSumit Saxena 		else
41572d1d418eSSumit Saxena 			process_evt_bh = 1;
41582d1d418eSSumit Saxena 		break;
41592d1d418eSSumit Saxena 	}
41602d1d418eSSumit Saxena 
41612d1d418eSSumit Saxena 	case MPI3_EVENT_DEVICE_STATUS_CHANGE:
41622d1d418eSSumit Saxena 	{
41632d1d418eSSumit Saxena 		process_evt_bh = 1;
41642d1d418eSSumit Saxena 		mpi3mr_devstatuschg_evt_th(sc, event_reply);
41652d1d418eSSumit Saxena 		break;
41662d1d418eSSumit Saxena 	}
41672d1d418eSSumit Saxena 	case MPI3_EVENT_SAS_TOPOLOGY_CHANGE_LIST:
41682d1d418eSSumit Saxena 	{
41692d1d418eSSumit Saxena 		process_evt_bh = 1;
41702d1d418eSSumit Saxena 		mpi3mr_sastopochg_evt_th(sc, event_reply);
41712d1d418eSSumit Saxena 		break;
41722d1d418eSSumit Saxena 	}
41732d1d418eSSumit Saxena 	case MPI3_EVENT_PCIE_TOPOLOGY_CHANGE_LIST:
41742d1d418eSSumit Saxena 	{
41752d1d418eSSumit Saxena 		process_evt_bh = 1;
41762d1d418eSSumit Saxena 		mpi3mr_pcietopochg_evt_th(sc, event_reply);
41772d1d418eSSumit Saxena 		break;
41782d1d418eSSumit Saxena 	}
41792d1d418eSSumit Saxena 	case MPI3_EVENT_PREPARE_FOR_RESET:
41802d1d418eSSumit Saxena 	{
41812d1d418eSSumit Saxena 		mpi3mr_preparereset_evt_th(sc, event_reply);
41822d1d418eSSumit Saxena 		ack_req = 0;
41832d1d418eSSumit Saxena 		break;
41842d1d418eSSumit Saxena 	}
41852d1d418eSSumit Saxena 	case MPI3_EVENT_DEVICE_INFO_CHANGED:
41862d1d418eSSumit Saxena 	case MPI3_EVENT_LOG_DATA:
41872d1d418eSSumit Saxena 	{
41882d1d418eSSumit Saxena 		process_evt_bh = 1;
41892d1d418eSSumit Saxena 		break;
41902d1d418eSSumit Saxena 	}
41912d1d418eSSumit Saxena 	case MPI3_EVENT_ENERGY_PACK_CHANGE:
41922d1d418eSSumit Saxena 	{
41932d1d418eSSumit Saxena 		mpi3mr_energypackchg_evt_th(sc, event_reply);
41942d1d418eSSumit Saxena 		break;
41952d1d418eSSumit Saxena 	}
41962d1d418eSSumit Saxena 	case MPI3_EVENT_CABLE_MGMT:
41972d1d418eSSumit Saxena 	{
41982d1d418eSSumit Saxena 		mpi3mr_cablemgmt_evt_th(sc, event_reply);
41992d1d418eSSumit Saxena 		break;
42002d1d418eSSumit Saxena 	}
42012d1d418eSSumit Saxena 
42022d1d418eSSumit Saxena 	case MPI3_EVENT_ENCL_DEVICE_STATUS_CHANGE:
42032d1d418eSSumit Saxena 	case MPI3_EVENT_SAS_DISCOVERY:
42042d1d418eSSumit Saxena 	case MPI3_EVENT_SAS_DEVICE_DISCOVERY_ERROR:
42052d1d418eSSumit Saxena 	case MPI3_EVENT_SAS_BROADCAST_PRIMITIVE:
42062d1d418eSSumit Saxena 	case MPI3_EVENT_PCIE_ENUMERATION:
42072d1d418eSSumit Saxena 		break;
42082d1d418eSSumit Saxena 	default:
42092d1d418eSSumit Saxena 		mpi3mr_dprint(sc, MPI3MR_INFO, "%s :Event 0x%02x is not handled by driver\n",
42102d1d418eSSumit Saxena 		    __func__, evt_type);
42112d1d418eSSumit Saxena 		break;
42122d1d418eSSumit Saxena 	}
42132d1d418eSSumit Saxena 
42142d1d418eSSumit Saxena 	if (process_evt_bh || ack_req) {
42152d1d418eSSumit Saxena 		fw_event = malloc(sizeof(struct mpi3mr_fw_event_work), M_MPI3MR,
42162d1d418eSSumit Saxena 		     M_ZERO|M_NOWAIT);
42172d1d418eSSumit Saxena 
42182d1d418eSSumit Saxena 		if (!fw_event) {
42192d1d418eSSumit Saxena 			printf("%s: allocate failed for fw_event\n", __func__);
42202d1d418eSSumit Saxena 			return;
42212d1d418eSSumit Saxena 		}
42222d1d418eSSumit Saxena 
42232d1d418eSSumit Saxena 		sz = le16toh(event_reply->EventDataLength) * 4;
42242d1d418eSSumit Saxena 		fw_event->event_data = malloc(sz, M_MPI3MR, M_ZERO|M_NOWAIT);
42252d1d418eSSumit Saxena 
42262d1d418eSSumit Saxena 		if (!fw_event->event_data) {
42272d1d418eSSumit Saxena 			printf("%s: allocate failed for event_data\n", __func__);
42282d1d418eSSumit Saxena 			free(fw_event, M_MPI3MR);
42292d1d418eSSumit Saxena 			return;
42302d1d418eSSumit Saxena 		}
42312d1d418eSSumit Saxena 
42322d1d418eSSumit Saxena 		bcopy(event_reply->EventData, fw_event->event_data, sz);
42332d1d418eSSumit Saxena 		fw_event->event = event_reply->Event;
42342d1d418eSSumit Saxena 		if ((event_reply->Event == MPI3_EVENT_SAS_TOPOLOGY_CHANGE_LIST ||
42352d1d418eSSumit Saxena 		    event_reply->Event == MPI3_EVENT_PCIE_TOPOLOGY_CHANGE_LIST ||
42362d1d418eSSumit Saxena 		    event_reply->Event == MPI3_EVENT_ENCL_DEVICE_STATUS_CHANGE ) &&
42372d1d418eSSumit Saxena 		    sc->track_mapping_events)
42382d1d418eSSumit Saxena 			sc->pending_map_events++;
42392d1d418eSSumit Saxena 
42402d1d418eSSumit Saxena 		/*
42412d1d418eSSumit Saxena 		 * Events should be processed after Port enable is completed.
42422d1d418eSSumit Saxena 		 */
42432d1d418eSSumit Saxena 		if ((event_reply->Event == MPI3_EVENT_SAS_TOPOLOGY_CHANGE_LIST ||
42442d1d418eSSumit Saxena 		    event_reply->Event == MPI3_EVENT_PCIE_TOPOLOGY_CHANGE_LIST ) &&
42452d1d418eSSumit Saxena 		    !(sc->mpi3mr_flags & MPI3MR_FLAGS_PORT_ENABLE_DONE))
42462d1d418eSSumit Saxena 			mpi3mr_startup_increment(sc->cam_sc);
42472d1d418eSSumit Saxena 
42482d1d418eSSumit Saxena 		fw_event->send_ack = ack_req;
42492d1d418eSSumit Saxena 		fw_event->event_context = le32toh(event_reply->EventContext);
42502d1d418eSSumit Saxena 		fw_event->event_data_size = sz;
42512d1d418eSSumit Saxena 		fw_event->process_event = process_evt_bh;
42522d1d418eSSumit Saxena 
42532d1d418eSSumit Saxena 		mtx_lock(&sc->fwevt_lock);
42542d1d418eSSumit Saxena 		TAILQ_INSERT_TAIL(&sc->cam_sc->ev_queue, fw_event, ev_link);
42552d1d418eSSumit Saxena 		taskqueue_enqueue(sc->cam_sc->ev_tq, &sc->cam_sc->ev_task);
42562d1d418eSSumit Saxena 		mtx_unlock(&sc->fwevt_lock);
42572d1d418eSSumit Saxena 
42582d1d418eSSumit Saxena 	}
42592d1d418eSSumit Saxena out:
42602d1d418eSSumit Saxena 	return;
42612d1d418eSSumit Saxena }
42622d1d418eSSumit Saxena 
mpi3mr_handle_events(struct mpi3mr_softc * sc,uintptr_t data,Mpi3DefaultReply_t * def_reply)42632d1d418eSSumit Saxena static void mpi3mr_handle_events(struct mpi3mr_softc *sc, uintptr_t data,
42642d1d418eSSumit Saxena     Mpi3DefaultReply_t *def_reply)
42652d1d418eSSumit Saxena {
42662d1d418eSSumit Saxena 	Mpi3EventNotificationReply_t *event_reply =
42672d1d418eSSumit Saxena 		(Mpi3EventNotificationReply_t *)def_reply;
42682d1d418eSSumit Saxena 
42692d1d418eSSumit Saxena 	sc->change_count = event_reply->IOCChangeCount;
42702d1d418eSSumit Saxena 	mpi3mr_display_event_data(sc, event_reply);
42712d1d418eSSumit Saxena 
42722d1d418eSSumit Saxena 	mpi3mr_process_events(sc, data, event_reply);
42732d1d418eSSumit Saxena }
42742d1d418eSSumit Saxena 
mpi3mr_process_admin_reply_desc(struct mpi3mr_softc * sc,Mpi3DefaultReplyDescriptor_t * reply_desc,U64 * reply_dma)42752d1d418eSSumit Saxena static void mpi3mr_process_admin_reply_desc(struct mpi3mr_softc *sc,
42762d1d418eSSumit Saxena     Mpi3DefaultReplyDescriptor_t *reply_desc, U64 *reply_dma)
42772d1d418eSSumit Saxena {
42782d1d418eSSumit Saxena 	U16 reply_desc_type, host_tag = 0, idx;
42792d1d418eSSumit Saxena 	U16 ioc_status = MPI3_IOCSTATUS_SUCCESS;
42802d1d418eSSumit Saxena 	U32 ioc_loginfo = 0;
42812d1d418eSSumit Saxena 	Mpi3StatusReplyDescriptor_t *status_desc;
42822d1d418eSSumit Saxena 	Mpi3AddressReplyDescriptor_t *addr_desc;
42832d1d418eSSumit Saxena 	Mpi3SuccessReplyDescriptor_t *success_desc;
42842d1d418eSSumit Saxena 	Mpi3DefaultReply_t *def_reply = NULL;
42852d1d418eSSumit Saxena 	struct mpi3mr_drvr_cmd *cmdptr = NULL;
42862d1d418eSSumit Saxena 	Mpi3SCSIIOReply_t *scsi_reply;
42872d1d418eSSumit Saxena 	U8 *sense_buf = NULL;
42882d1d418eSSumit Saxena 
42892d1d418eSSumit Saxena 	*reply_dma = 0;
42902d1d418eSSumit Saxena 	reply_desc_type = reply_desc->ReplyFlags &
42912d1d418eSSumit Saxena 			    MPI3_REPLY_DESCRIPT_FLAGS_TYPE_MASK;
42922d1d418eSSumit Saxena 	switch (reply_desc_type) {
42932d1d418eSSumit Saxena 	case MPI3_REPLY_DESCRIPT_FLAGS_TYPE_STATUS:
42942d1d418eSSumit Saxena 		status_desc = (Mpi3StatusReplyDescriptor_t *)reply_desc;
42952d1d418eSSumit Saxena 		host_tag = status_desc->HostTag;
42962d1d418eSSumit Saxena 		ioc_status = status_desc->IOCStatus;
4297baabb919SChandrakanth patil 		if (ioc_status & MPI3_IOCSTATUS_STATUS_MASK)
42982d1d418eSSumit Saxena 			ioc_loginfo = status_desc->IOCLogInfo;
4299baabb919SChandrakanth patil 		ioc_status &= MPI3_IOCSTATUS_STATUS_MASK;
43002d1d418eSSumit Saxena 		break;
43012d1d418eSSumit Saxena 	case MPI3_REPLY_DESCRIPT_FLAGS_TYPE_ADDRESS_REPLY:
43022d1d418eSSumit Saxena 		addr_desc = (Mpi3AddressReplyDescriptor_t *)reply_desc;
43032d1d418eSSumit Saxena 		*reply_dma = addr_desc->ReplyFrameAddress;
43042d1d418eSSumit Saxena 		def_reply = mpi3mr_get_reply_virt_addr(sc, *reply_dma);
43052d1d418eSSumit Saxena 		if (def_reply == NULL)
43062d1d418eSSumit Saxena 			goto out;
43072d1d418eSSumit Saxena 		host_tag = def_reply->HostTag;
43082d1d418eSSumit Saxena 		ioc_status = def_reply->IOCStatus;
4309baabb919SChandrakanth patil 		if (ioc_status & MPI3_IOCSTATUS_STATUS_MASK)
43102d1d418eSSumit Saxena 			ioc_loginfo = def_reply->IOCLogInfo;
4311baabb919SChandrakanth patil 		ioc_status &= MPI3_IOCSTATUS_STATUS_MASK;
43122d1d418eSSumit Saxena 		if (def_reply->Function == MPI3_FUNCTION_SCSI_IO) {
43132d1d418eSSumit Saxena 			scsi_reply = (Mpi3SCSIIOReply_t *)def_reply;
43142d1d418eSSumit Saxena 			sense_buf = mpi3mr_get_sensebuf_virt_addr(sc,
43152d1d418eSSumit Saxena 			    scsi_reply->SenseDataBufferAddress);
43162d1d418eSSumit Saxena 		}
43172d1d418eSSumit Saxena 		break;
43182d1d418eSSumit Saxena 	case MPI3_REPLY_DESCRIPT_FLAGS_TYPE_SUCCESS:
43192d1d418eSSumit Saxena 		success_desc = (Mpi3SuccessReplyDescriptor_t *)reply_desc;
43202d1d418eSSumit Saxena 		host_tag = success_desc->HostTag;
43212d1d418eSSumit Saxena 		break;
43222d1d418eSSumit Saxena 	default:
43232d1d418eSSumit Saxena 		break;
43242d1d418eSSumit Saxena 	}
43252d1d418eSSumit Saxena 	switch (host_tag) {
43262d1d418eSSumit Saxena 	case MPI3MR_HOSTTAG_INITCMDS:
43272d1d418eSSumit Saxena 		cmdptr = &sc->init_cmds;
43282d1d418eSSumit Saxena 		break;
43292d1d418eSSumit Saxena 	case MPI3MR_HOSTTAG_IOCTLCMDS:
43302d1d418eSSumit Saxena 		cmdptr = &sc->ioctl_cmds;
43312d1d418eSSumit Saxena 		break;
43322d1d418eSSumit Saxena 	case MPI3MR_HOSTTAG_TMS:
43332d1d418eSSumit Saxena 		cmdptr = &sc->host_tm_cmds;
43342d1d418eSSumit Saxena 		wakeup((void *)&sc->tm_chan);
43352d1d418eSSumit Saxena 		break;
43362d1d418eSSumit Saxena 	case MPI3MR_HOSTTAG_PELABORT:
43372d1d418eSSumit Saxena 		cmdptr = &sc->pel_abort_cmd;
43382d1d418eSSumit Saxena 		break;
43392d1d418eSSumit Saxena 	case MPI3MR_HOSTTAG_PELWAIT:
43402d1d418eSSumit Saxena 		cmdptr = &sc->pel_cmds;
43412d1d418eSSumit Saxena 		break;
43422d1d418eSSumit Saxena 	case MPI3MR_HOSTTAG_INVALID:
43432d1d418eSSumit Saxena 		if (def_reply && def_reply->Function ==
43442d1d418eSSumit Saxena 		    MPI3_FUNCTION_EVENT_NOTIFICATION)
43452d1d418eSSumit Saxena 			mpi3mr_handle_events(sc, *reply_dma ,def_reply);
43462d1d418eSSumit Saxena 	default:
43472d1d418eSSumit Saxena 		break;
43482d1d418eSSumit Saxena 	}
43492d1d418eSSumit Saxena 
43502d1d418eSSumit Saxena 	if (host_tag >= MPI3MR_HOSTTAG_DEVRMCMD_MIN &&
43512d1d418eSSumit Saxena 	    host_tag <= MPI3MR_HOSTTAG_DEVRMCMD_MAX ) {
43522d1d418eSSumit Saxena 		idx = host_tag - MPI3MR_HOSTTAG_DEVRMCMD_MIN;
43532d1d418eSSumit Saxena 		cmdptr = &sc->dev_rmhs_cmds[idx];
43542d1d418eSSumit Saxena 	}
43552d1d418eSSumit Saxena 
43562d1d418eSSumit Saxena 	if (host_tag >= MPI3MR_HOSTTAG_EVTACKCMD_MIN &&
43572d1d418eSSumit Saxena 	    host_tag <= MPI3MR_HOSTTAG_EVTACKCMD_MAX) {
43582d1d418eSSumit Saxena 		idx = host_tag - MPI3MR_HOSTTAG_EVTACKCMD_MIN;
43592d1d418eSSumit Saxena 		cmdptr = &sc->evtack_cmds[idx];
43602d1d418eSSumit Saxena 	}
43612d1d418eSSumit Saxena 
43622d1d418eSSumit Saxena 	if (cmdptr) {
43632d1d418eSSumit Saxena 		if (cmdptr->state & MPI3MR_CMD_PENDING) {
43642d1d418eSSumit Saxena 			cmdptr->state |= MPI3MR_CMD_COMPLETE;
43652d1d418eSSumit Saxena 			cmdptr->ioc_loginfo = ioc_loginfo;
43662d1d418eSSumit Saxena 			cmdptr->ioc_status = ioc_status;
43672d1d418eSSumit Saxena 			cmdptr->state &= ~MPI3MR_CMD_PENDING;
43682d1d418eSSumit Saxena 			if (def_reply) {
43692d1d418eSSumit Saxena 				cmdptr->state |= MPI3MR_CMD_REPLYVALID;
43702d1d418eSSumit Saxena 				memcpy((U8 *)cmdptr->reply, (U8 *)def_reply,
43712d1d418eSSumit Saxena 				    sc->reply_sz);
43722d1d418eSSumit Saxena 			}
43732d1d418eSSumit Saxena 			if (sense_buf && cmdptr->sensebuf) {
43742d1d418eSSumit Saxena 				cmdptr->is_senseprst = 1;
43752d1d418eSSumit Saxena 				memcpy(cmdptr->sensebuf, sense_buf,
43762d1d418eSSumit Saxena 				    MPI3MR_SENSEBUF_SZ);
43772d1d418eSSumit Saxena 			}
43782d1d418eSSumit Saxena 			if (cmdptr->is_waiting) {
43792d1d418eSSumit Saxena 				complete(&cmdptr->completion);
43802d1d418eSSumit Saxena 				cmdptr->is_waiting = 0;
43812d1d418eSSumit Saxena 			} else if (cmdptr->callback)
43822d1d418eSSumit Saxena 				cmdptr->callback(sc, cmdptr);
43832d1d418eSSumit Saxena 		}
43842d1d418eSSumit Saxena 	}
43852d1d418eSSumit Saxena out:
43862d1d418eSSumit Saxena 	if (sense_buf != NULL)
43872d1d418eSSumit Saxena 		mpi3mr_repost_sense_buf(sc,
43882d1d418eSSumit Saxena 		    scsi_reply->SenseDataBufferAddress);
43892d1d418eSSumit Saxena 	return;
43902d1d418eSSumit Saxena }
43912d1d418eSSumit Saxena 
43922d1d418eSSumit Saxena /*
43932d1d418eSSumit Saxena  * mpi3mr_complete_admin_cmd:	ISR routine for admin commands
43942d1d418eSSumit Saxena  * @sc:				Adapter's soft instance
43952d1d418eSSumit Saxena  *
43962d1d418eSSumit Saxena  * This function processes admin command completions.
43972d1d418eSSumit Saxena  */
mpi3mr_complete_admin_cmd(struct mpi3mr_softc * sc)43982d1d418eSSumit Saxena static int mpi3mr_complete_admin_cmd(struct mpi3mr_softc *sc)
43992d1d418eSSumit Saxena {
44002d1d418eSSumit Saxena 	U32 exp_phase = sc->admin_reply_ephase;
44012d1d418eSSumit Saxena 	U32 adm_reply_ci = sc->admin_reply_ci;
44022d1d418eSSumit Saxena 	U32 num_adm_reply = 0;
44032d1d418eSSumit Saxena 	U64 reply_dma = 0;
44042d1d418eSSumit Saxena 	Mpi3DefaultReplyDescriptor_t *reply_desc;
4405eb7a4b35SChandrakanth patil 	U16 threshold_comps = 0;
44062d1d418eSSumit Saxena 
44072d1d418eSSumit Saxena 	mtx_lock_spin(&sc->admin_reply_lock);
44082d1d418eSSumit Saxena 	if (sc->admin_in_use == false) {
44092d1d418eSSumit Saxena 		sc->admin_in_use = true;
44102d1d418eSSumit Saxena 		mtx_unlock_spin(&sc->admin_reply_lock);
44112d1d418eSSumit Saxena 	} else {
44122d1d418eSSumit Saxena 		mtx_unlock_spin(&sc->admin_reply_lock);
44132d1d418eSSumit Saxena 		return 0;
44142d1d418eSSumit Saxena 	}
44152d1d418eSSumit Saxena 
44162d1d418eSSumit Saxena 	reply_desc = (Mpi3DefaultReplyDescriptor_t *)sc->admin_reply +
44172d1d418eSSumit Saxena 		adm_reply_ci;
44182d1d418eSSumit Saxena 
44192d1d418eSSumit Saxena 	if ((reply_desc->ReplyFlags &
44202d1d418eSSumit Saxena 	     MPI3_REPLY_DESCRIPT_FLAGS_PHASE_MASK) != exp_phase) {
44212d1d418eSSumit Saxena 		mtx_lock_spin(&sc->admin_reply_lock);
44222d1d418eSSumit Saxena 		sc->admin_in_use = false;
44232d1d418eSSumit Saxena 		mtx_unlock_spin(&sc->admin_reply_lock);
44242d1d418eSSumit Saxena 		return 0;
44252d1d418eSSumit Saxena 	}
44262d1d418eSSumit Saxena 
44272d1d418eSSumit Saxena 	do {
44282d1d418eSSumit Saxena 		sc->admin_req_ci = reply_desc->RequestQueueCI;
44292d1d418eSSumit Saxena 		mpi3mr_process_admin_reply_desc(sc, reply_desc, &reply_dma);
44302d1d418eSSumit Saxena 		if (reply_dma)
44312d1d418eSSumit Saxena 			mpi3mr_repost_reply_buf(sc, reply_dma);
44322d1d418eSSumit Saxena 		num_adm_reply++;
44332d1d418eSSumit Saxena 		if (++adm_reply_ci == sc->num_admin_replies) {
44342d1d418eSSumit Saxena 			adm_reply_ci = 0;
44352d1d418eSSumit Saxena 			exp_phase ^= 1;
44362d1d418eSSumit Saxena 		}
44372d1d418eSSumit Saxena 		reply_desc =
44382d1d418eSSumit Saxena 			(Mpi3DefaultReplyDescriptor_t *)sc->admin_reply +
44392d1d418eSSumit Saxena 			    adm_reply_ci;
44402d1d418eSSumit Saxena 		if ((reply_desc->ReplyFlags &
44412d1d418eSSumit Saxena 		     MPI3_REPLY_DESCRIPT_FLAGS_PHASE_MASK) != exp_phase)
44422d1d418eSSumit Saxena 			break;
4443eb7a4b35SChandrakanth patil 
4444eb7a4b35SChandrakanth patil 		if (++threshold_comps == MPI3MR_THRESHOLD_REPLY_COUNT) {
4445eb7a4b35SChandrakanth patil 			mpi3mr_regwrite(sc, MPI3_SYSIF_ADMIN_REPLY_Q_CI_OFFSET, adm_reply_ci);
4446eb7a4b35SChandrakanth patil 			threshold_comps = 0;
4447eb7a4b35SChandrakanth patil 		}
44482d1d418eSSumit Saxena 	} while (1);
44492d1d418eSSumit Saxena 
44502d1d418eSSumit Saxena 	mpi3mr_regwrite(sc, MPI3_SYSIF_ADMIN_REPLY_Q_CI_OFFSET, adm_reply_ci);
44512d1d418eSSumit Saxena 	sc->admin_reply_ci = adm_reply_ci;
44522d1d418eSSumit Saxena 	sc->admin_reply_ephase = exp_phase;
44532d1d418eSSumit Saxena 	mtx_lock_spin(&sc->admin_reply_lock);
44542d1d418eSSumit Saxena 	sc->admin_in_use = false;
44552d1d418eSSumit Saxena 	mtx_unlock_spin(&sc->admin_reply_lock);
44562d1d418eSSumit Saxena 	return num_adm_reply;
44572d1d418eSSumit Saxena }
44582d1d418eSSumit Saxena 
44592d1d418eSSumit Saxena static void
mpi3mr_cmd_done(struct mpi3mr_softc * sc,struct mpi3mr_cmd * cmd)44602d1d418eSSumit Saxena mpi3mr_cmd_done(struct mpi3mr_softc *sc, struct mpi3mr_cmd *cmd)
44612d1d418eSSumit Saxena {
44622d1d418eSSumit Saxena 	mpi3mr_unmap_request(sc, cmd);
44632d1d418eSSumit Saxena 
44642d1d418eSSumit Saxena 	mtx_lock(&sc->mpi3mr_mtx);
44652d1d418eSSumit Saxena 	if (cmd->callout_owner) {
44662d1d418eSSumit Saxena 		callout_stop(&cmd->callout);
44672d1d418eSSumit Saxena 		cmd->callout_owner = false;
44682d1d418eSSumit Saxena 	}
44692d1d418eSSumit Saxena 
44702d1d418eSSumit Saxena 	if (sc->unrecoverable)
44712d1d418eSSumit Saxena 		mpi3mr_set_ccbstatus(cmd->ccb, CAM_DEV_NOT_THERE);
44722d1d418eSSumit Saxena 
44732d1d418eSSumit Saxena 	xpt_done(cmd->ccb);
44742d1d418eSSumit Saxena 	cmd->ccb = NULL;
44752d1d418eSSumit Saxena 	mtx_unlock(&sc->mpi3mr_mtx);
44762d1d418eSSumit Saxena 	mpi3mr_release_command(cmd);
44772d1d418eSSumit Saxena }
44782d1d418eSSumit Saxena 
mpi3mr_process_op_reply_desc(struct mpi3mr_softc * sc,Mpi3DefaultReplyDescriptor_t * reply_desc,U64 * reply_dma)44792d1d418eSSumit Saxena void mpi3mr_process_op_reply_desc(struct mpi3mr_softc *sc,
44802d1d418eSSumit Saxena     Mpi3DefaultReplyDescriptor_t *reply_desc, U64 *reply_dma)
44812d1d418eSSumit Saxena {
44822d1d418eSSumit Saxena 	U16 reply_desc_type, host_tag = 0;
44832d1d418eSSumit Saxena 	U16 ioc_status = MPI3_IOCSTATUS_SUCCESS;
44842d1d418eSSumit Saxena 	U32 ioc_loginfo = 0;
44852d1d418eSSumit Saxena 	Mpi3StatusReplyDescriptor_t *status_desc = NULL;
44862d1d418eSSumit Saxena 	Mpi3AddressReplyDescriptor_t *addr_desc = NULL;
44872d1d418eSSumit Saxena 	Mpi3SuccessReplyDescriptor_t *success_desc = NULL;
44882d1d418eSSumit Saxena 	Mpi3SCSIIOReply_t *scsi_reply = NULL;
44892d1d418eSSumit Saxena 	U8 *sense_buf = NULL;
44902d1d418eSSumit Saxena 	U8 scsi_state = 0, scsi_status = 0, sense_state = 0;
44912d1d418eSSumit Saxena 	U32 xfer_count = 0, sense_count =0, resp_data = 0;
44922d1d418eSSumit Saxena 	struct mpi3mr_cmd *cm = NULL;
44932d1d418eSSumit Saxena 	union ccb *ccb;
44942d1d418eSSumit Saxena 	struct ccb_scsiio *csio;
44952d1d418eSSumit Saxena 	struct mpi3mr_cam_softc *cam_sc;
44962d1d418eSSumit Saxena 	U32 target_id;
44972d1d418eSSumit Saxena 	U8 *scsi_cdb;
44982d1d418eSSumit Saxena 	struct mpi3mr_target *target = NULL;
44992d1d418eSSumit Saxena 	U32 ioc_pend_data_len = 0, tg_pend_data_len = 0, data_len_blks = 0;
45002d1d418eSSumit Saxena 	struct mpi3mr_throttle_group_info *tg = NULL;
45012d1d418eSSumit Saxena 	U8 throttle_enabled_dev = 0;
45022d1d418eSSumit Saxena 	static int ratelimit;
45032d1d418eSSumit Saxena 
45042d1d418eSSumit Saxena 	*reply_dma = 0;
45052d1d418eSSumit Saxena 	reply_desc_type = reply_desc->ReplyFlags &
45062d1d418eSSumit Saxena 			    MPI3_REPLY_DESCRIPT_FLAGS_TYPE_MASK;
45072d1d418eSSumit Saxena 	switch (reply_desc_type) {
45082d1d418eSSumit Saxena 	case MPI3_REPLY_DESCRIPT_FLAGS_TYPE_STATUS:
45092d1d418eSSumit Saxena 		status_desc = (Mpi3StatusReplyDescriptor_t *)reply_desc;
45102d1d418eSSumit Saxena 		host_tag = status_desc->HostTag;
45112d1d418eSSumit Saxena 		ioc_status = status_desc->IOCStatus;
4512baabb919SChandrakanth patil 		if (ioc_status & MPI3_IOCSTATUS_STATUS_MASK)
45132d1d418eSSumit Saxena 			ioc_loginfo = status_desc->IOCLogInfo;
4514baabb919SChandrakanth patil 		ioc_status &= MPI3_IOCSTATUS_STATUS_MASK;
45152d1d418eSSumit Saxena 		break;
45162d1d418eSSumit Saxena 	case MPI3_REPLY_DESCRIPT_FLAGS_TYPE_ADDRESS_REPLY:
45172d1d418eSSumit Saxena 		addr_desc = (Mpi3AddressReplyDescriptor_t *)reply_desc;
45182d1d418eSSumit Saxena 		*reply_dma = addr_desc->ReplyFrameAddress;
45192d1d418eSSumit Saxena 		scsi_reply = mpi3mr_get_reply_virt_addr(sc,
45202d1d418eSSumit Saxena 		    *reply_dma);
45212d1d418eSSumit Saxena 		if (scsi_reply == NULL) {
45222d1d418eSSumit Saxena 			mpi3mr_dprint(sc, MPI3MR_ERROR, "scsi_reply is NULL, "
45232d1d418eSSumit Saxena 			    "this shouldn't happen, reply_desc: %p\n",
45242d1d418eSSumit Saxena 			    reply_desc);
45252d1d418eSSumit Saxena 			goto out;
45262d1d418eSSumit Saxena 		}
45272d1d418eSSumit Saxena 
45282d1d418eSSumit Saxena 		host_tag = scsi_reply->HostTag;
45292d1d418eSSumit Saxena 		ioc_status = scsi_reply->IOCStatus;
45302d1d418eSSumit Saxena 		scsi_status = scsi_reply->SCSIStatus;
45312d1d418eSSumit Saxena 		scsi_state = scsi_reply->SCSIState;
45322d1d418eSSumit Saxena 		sense_state = (scsi_state & MPI3_SCSI_STATE_SENSE_MASK);
45332d1d418eSSumit Saxena 		xfer_count = scsi_reply->TransferCount;
45342d1d418eSSumit Saxena 		sense_count = scsi_reply->SenseCount;
45352d1d418eSSumit Saxena 		resp_data = scsi_reply->ResponseData;
45362d1d418eSSumit Saxena 		sense_buf = mpi3mr_get_sensebuf_virt_addr(sc,
45372d1d418eSSumit Saxena 		    scsi_reply->SenseDataBufferAddress);
4538baabb919SChandrakanth patil 		if (ioc_status & MPI3_IOCSTATUS_STATUS_MASK)
45392d1d418eSSumit Saxena 			ioc_loginfo = scsi_reply->IOCLogInfo;
4540baabb919SChandrakanth patil 		ioc_status &= MPI3_IOCSTATUS_STATUS_MASK;
45412d1d418eSSumit Saxena 		if (sense_state == MPI3_SCSI_STATE_SENSE_BUFF_Q_EMPTY)
45422d1d418eSSumit Saxena 			mpi3mr_dprint(sc, MPI3MR_ERROR, "Ran out of sense buffers\n");
45432d1d418eSSumit Saxena 
45442d1d418eSSumit Saxena 		break;
45452d1d418eSSumit Saxena 	case MPI3_REPLY_DESCRIPT_FLAGS_TYPE_SUCCESS:
45462d1d418eSSumit Saxena 		success_desc = (Mpi3SuccessReplyDescriptor_t *)reply_desc;
45472d1d418eSSumit Saxena 		host_tag = success_desc->HostTag;
45482d1d418eSSumit Saxena 
45492d1d418eSSumit Saxena 	default:
45502d1d418eSSumit Saxena 		break;
45512d1d418eSSumit Saxena 	}
45522d1d418eSSumit Saxena 
45532d1d418eSSumit Saxena 	cm = sc->cmd_list[host_tag];
45542d1d418eSSumit Saxena 
45552d1d418eSSumit Saxena 	if (cm->state == MPI3MR_CMD_STATE_FREE)
45562d1d418eSSumit Saxena 		goto out;
45572d1d418eSSumit Saxena 
45582d1d418eSSumit Saxena 	cam_sc = sc->cam_sc;
45592d1d418eSSumit Saxena 	ccb = cm->ccb;
45602d1d418eSSumit Saxena 	csio = &ccb->csio;
45612d1d418eSSumit Saxena 	target_id = csio->ccb_h.target_id;
45622d1d418eSSumit Saxena 
45632d1d418eSSumit Saxena 	scsi_cdb = scsiio_cdb_ptr(csio);
45642d1d418eSSumit Saxena 
45652d1d418eSSumit Saxena 	target = mpi3mr_find_target_by_per_id(cam_sc, target_id);
45662d1d418eSSumit Saxena 	if (sc->iot_enable) {
45672d1d418eSSumit Saxena 		data_len_blks = csio->dxfer_len >> 9;
45682d1d418eSSumit Saxena 
45692d1d418eSSumit Saxena 		if (target) {
45702d1d418eSSumit Saxena 			tg = target->throttle_group;
45712d1d418eSSumit Saxena 			throttle_enabled_dev =
45722d1d418eSSumit Saxena 				target->io_throttle_enabled;
45732d1d418eSSumit Saxena 		}
45742d1d418eSSumit Saxena 
45752d1d418eSSumit Saxena 		if ((data_len_blks >= sc->io_throttle_data_length) &&
45762d1d418eSSumit Saxena 		     throttle_enabled_dev) {
45772d1d418eSSumit Saxena 			mpi3mr_atomic_sub(&sc->pend_large_data_sz, data_len_blks);
45782d1d418eSSumit Saxena 			ioc_pend_data_len = mpi3mr_atomic_read(
45792d1d418eSSumit Saxena 			    &sc->pend_large_data_sz);
45802d1d418eSSumit Saxena 			if (tg) {
45812d1d418eSSumit Saxena 				mpi3mr_atomic_sub(&tg->pend_large_data_sz,
45822d1d418eSSumit Saxena 					data_len_blks);
45832d1d418eSSumit Saxena 				tg_pend_data_len = mpi3mr_atomic_read(&tg->pend_large_data_sz);
45842d1d418eSSumit Saxena 				if (ratelimit % 1000) {
45852d1d418eSSumit Saxena 					mpi3mr_dprint(sc, MPI3MR_IOT,
45862d1d418eSSumit Saxena 						"large vd_io completion persist_id(%d), handle(0x%04x), data_len(%d),"
45872d1d418eSSumit Saxena 						"ioc_pending(%d), tg_pending(%d), ioc_low(%d), tg_low(%d)\n",
45882d1d418eSSumit Saxena 						    target->per_id,
45892d1d418eSSumit Saxena 						    target->dev_handle,
45902d1d418eSSumit Saxena 						    data_len_blks, ioc_pend_data_len,
45912d1d418eSSumit Saxena 						    tg_pend_data_len,
45922d1d418eSSumit Saxena 						    sc->io_throttle_low,
45932d1d418eSSumit Saxena 						    tg->low);
45942d1d418eSSumit Saxena 					ratelimit++;
45952d1d418eSSumit Saxena 				}
45962d1d418eSSumit Saxena 				if (tg->io_divert  && ((ioc_pend_data_len <=
45972d1d418eSSumit Saxena 				    sc->io_throttle_low) &&
45982d1d418eSSumit Saxena 				    (tg_pend_data_len <= tg->low))) {
45992d1d418eSSumit Saxena 					tg->io_divert = 0;
46002d1d418eSSumit Saxena 					mpi3mr_dprint(sc, MPI3MR_IOT,
46012d1d418eSSumit Saxena 						"VD: Coming out of divert perst_id(%d) tg_id(%d)\n",
46022d1d418eSSumit Saxena 						target->per_id, tg->id);
46032d1d418eSSumit Saxena 					mpi3mr_set_io_divert_for_all_vd_in_tg(
46042d1d418eSSumit Saxena 					    sc, tg, 0);
46052d1d418eSSumit Saxena 				}
46062d1d418eSSumit Saxena 			} else {
46072d1d418eSSumit Saxena 				if (ratelimit % 1000) {
46082d1d418eSSumit Saxena 					mpi3mr_dprint(sc, MPI3MR_IOT,
46092d1d418eSSumit Saxena 					    "large pd_io completion persist_id(%d), handle(0x%04x), data_len(%d), ioc_pending(%d), ioc_low(%d)\n",
46102d1d418eSSumit Saxena 					    target->per_id,
46112d1d418eSSumit Saxena 					    target->dev_handle,
46122d1d418eSSumit Saxena 					    data_len_blks, ioc_pend_data_len,
46132d1d418eSSumit Saxena 					    sc->io_throttle_low);
46142d1d418eSSumit Saxena 					ratelimit++;
46152d1d418eSSumit Saxena 				}
46162d1d418eSSumit Saxena 
46172d1d418eSSumit Saxena 				if (ioc_pend_data_len <= sc->io_throttle_low) {
46182d1d418eSSumit Saxena 					target->io_divert = 0;
46192d1d418eSSumit Saxena 					mpi3mr_dprint(sc, MPI3MR_IOT,
46202d1d418eSSumit Saxena 						"PD: Coming out of divert perst_id(%d)\n",
46212d1d418eSSumit Saxena 						target->per_id);
46222d1d418eSSumit Saxena 				}
46232d1d418eSSumit Saxena 			}
46242d1d418eSSumit Saxena 
46252d1d418eSSumit Saxena 			} else if (target->io_divert) {
46262d1d418eSSumit Saxena 			ioc_pend_data_len = mpi3mr_atomic_read(&sc->pend_large_data_sz);
46272d1d418eSSumit Saxena 			if (!tg) {
46282d1d418eSSumit Saxena 				if (ratelimit % 1000) {
46292d1d418eSSumit Saxena 					mpi3mr_dprint(sc, MPI3MR_IOT,
46302d1d418eSSumit Saxena 					    "pd_io completion persist_id(%d), handle(0x%04x), data_len(%d), ioc_pending(%d), ioc_low(%d)\n",
46312d1d418eSSumit Saxena 					    target->per_id,
46322d1d418eSSumit Saxena 					    target->dev_handle,
46332d1d418eSSumit Saxena 					    data_len_blks, ioc_pend_data_len,
46342d1d418eSSumit Saxena 					    sc->io_throttle_low);
46352d1d418eSSumit Saxena 					ratelimit++;
46362d1d418eSSumit Saxena 				}
46372d1d418eSSumit Saxena 
46382d1d418eSSumit Saxena 				if ( ioc_pend_data_len <= sc->io_throttle_low) {
46392d1d418eSSumit Saxena 					mpi3mr_dprint(sc, MPI3MR_IOT,
46402d1d418eSSumit Saxena 						"PD: Coming out of divert perst_id(%d)\n",
46412d1d418eSSumit Saxena 						target->per_id);
46422d1d418eSSumit Saxena 					target->io_divert = 0;
46432d1d418eSSumit Saxena 				}
46442d1d418eSSumit Saxena 
46452d1d418eSSumit Saxena 			} else if (ioc_pend_data_len <= sc->io_throttle_low) {
46462d1d418eSSumit Saxena 				tg_pend_data_len = mpi3mr_atomic_read(&tg->pend_large_data_sz);
46472d1d418eSSumit Saxena 				if (ratelimit % 1000) {
46482d1d418eSSumit Saxena 					mpi3mr_dprint(sc, MPI3MR_IOT,
46492d1d418eSSumit Saxena 						"vd_io completion persist_id(%d), handle(0x%04x), data_len(%d),"
46502d1d418eSSumit Saxena 						"ioc_pending(%d), tg_pending(%d), ioc_low(%d), tg_low(%d)\n",
46512d1d418eSSumit Saxena 						    target->per_id,
46522d1d418eSSumit Saxena 						    target->dev_handle,
46532d1d418eSSumit Saxena 						    data_len_blks, ioc_pend_data_len,
46542d1d418eSSumit Saxena 						    tg_pend_data_len,
46552d1d418eSSumit Saxena 						    sc->io_throttle_low,
46562d1d418eSSumit Saxena 						    tg->low);
46572d1d418eSSumit Saxena 					ratelimit++;
46582d1d418eSSumit Saxena 				}
46592d1d418eSSumit Saxena 				if (tg->io_divert  && (tg_pend_data_len <= tg->low)) {
46602d1d418eSSumit Saxena 					tg->io_divert = 0;
46612d1d418eSSumit Saxena 					mpi3mr_dprint(sc, MPI3MR_IOT,
46622d1d418eSSumit Saxena 						"VD: Coming out of divert perst_id(%d) tg_id(%d)\n",
46632d1d418eSSumit Saxena 						target->per_id, tg->id);
46642d1d418eSSumit Saxena 					mpi3mr_set_io_divert_for_all_vd_in_tg(
46652d1d418eSSumit Saxena 					    sc, tg, 0);
46662d1d418eSSumit Saxena 				}
46672d1d418eSSumit Saxena 
46682d1d418eSSumit Saxena 			}
46692d1d418eSSumit Saxena 		}
46702d1d418eSSumit Saxena 	}
46712d1d418eSSumit Saxena 
46722d1d418eSSumit Saxena 	if (success_desc) {
46732d1d418eSSumit Saxena 		mpi3mr_set_ccbstatus(ccb, CAM_REQ_CMP);
46742d1d418eSSumit Saxena 		goto out_success;
46752d1d418eSSumit Saxena 	}
46762d1d418eSSumit Saxena 
46772d1d418eSSumit Saxena 	if (ioc_status == MPI3_IOCSTATUS_SCSI_DATA_UNDERRUN
46782d1d418eSSumit Saxena 	    && xfer_count == 0 && (scsi_status == MPI3_SCSI_STATUS_BUSY ||
46792d1d418eSSumit Saxena 	    scsi_status == MPI3_SCSI_STATUS_RESERVATION_CONFLICT ||
46802d1d418eSSumit Saxena 	    scsi_status == MPI3_SCSI_STATUS_TASK_SET_FULL))
46812d1d418eSSumit Saxena 		ioc_status = MPI3_IOCSTATUS_SUCCESS;
46822d1d418eSSumit Saxena 
46832d1d418eSSumit Saxena 	if ((sense_state == MPI3_SCSI_STATE_SENSE_VALID) && sense_count
46842d1d418eSSumit Saxena 	    && sense_buf) {
46852d1d418eSSumit Saxena 		int sense_len, returned_sense_len;
46862d1d418eSSumit Saxena 
46872d1d418eSSumit Saxena 		returned_sense_len = min(le32toh(sense_count),
46882d1d418eSSumit Saxena 		    sizeof(struct scsi_sense_data));
46892d1d418eSSumit Saxena 		if (returned_sense_len < csio->sense_len)
46902d1d418eSSumit Saxena 			csio->sense_resid = csio->sense_len -
46912d1d418eSSumit Saxena 			    returned_sense_len;
46922d1d418eSSumit Saxena 		else
46932d1d418eSSumit Saxena 			csio->sense_resid = 0;
46942d1d418eSSumit Saxena 
46952d1d418eSSumit Saxena 		sense_len = min(returned_sense_len,
46962d1d418eSSumit Saxena 		    csio->sense_len - csio->sense_resid);
46972d1d418eSSumit Saxena 		bzero(&csio->sense_data, sizeof(csio->sense_data));
46982d1d418eSSumit Saxena 		bcopy(sense_buf, &csio->sense_data, sense_len);
46992d1d418eSSumit Saxena 		ccb->ccb_h.status |= CAM_AUTOSNS_VALID;
47002d1d418eSSumit Saxena 	}
47012d1d418eSSumit Saxena 
47022d1d418eSSumit Saxena 	switch (ioc_status) {
47032d1d418eSSumit Saxena 	case MPI3_IOCSTATUS_BUSY:
47042d1d418eSSumit Saxena 	case MPI3_IOCSTATUS_INSUFFICIENT_RESOURCES:
47052d1d418eSSumit Saxena 		mpi3mr_set_ccbstatus(ccb, CAM_REQUEUE_REQ);
47062d1d418eSSumit Saxena 		break;
47072d1d418eSSumit Saxena 	case MPI3_IOCSTATUS_SCSI_DEVICE_NOT_THERE:
47082d1d418eSSumit Saxena 		/*
47092d1d418eSSumit Saxena 		 * If devinfo is 0 this will be a volume.  In that case don't
47102d1d418eSSumit Saxena 		 * tell CAM that the volume is not there.  We want volumes to
47112d1d418eSSumit Saxena 		 * be enumerated until they are deleted/removed, not just
47122d1d418eSSumit Saxena 		 * failed.
47132d1d418eSSumit Saxena 		 */
47142d1d418eSSumit Saxena 		if (cm->targ->devinfo == 0)
47152d1d418eSSumit Saxena 			mpi3mr_set_ccbstatus(ccb, CAM_REQ_CMP);
47162d1d418eSSumit Saxena 		else
47172d1d418eSSumit Saxena 			mpi3mr_set_ccbstatus(ccb, CAM_DEV_NOT_THERE);
47182d1d418eSSumit Saxena 		break;
47192d1d418eSSumit Saxena 	case MPI3_IOCSTATUS_SCSI_TASK_TERMINATED:
47202d1d418eSSumit Saxena 	case MPI3_IOCSTATUS_SCSI_IOC_TERMINATED:
47212d1d418eSSumit Saxena 	case MPI3_IOCSTATUS_SCSI_EXT_TERMINATED:
47222d1d418eSSumit Saxena 		mpi3mr_set_ccbstatus(ccb, CAM_SCSI_BUSY);
47232d1d418eSSumit Saxena 		mpi3mr_dprint(sc, MPI3MR_TRACE,
47242d1d418eSSumit Saxena 		    "func: %s line:%d tgt %u Hosttag %u loginfo %x\n",
47252d1d418eSSumit Saxena 		    __func__, __LINE__,
47262d1d418eSSumit Saxena 		    target_id, cm->hosttag,
47272d1d418eSSumit Saxena 		    le32toh(scsi_reply->IOCLogInfo));
47282d1d418eSSumit Saxena 		mpi3mr_dprint(sc, MPI3MR_TRACE,
47292d1d418eSSumit Saxena 		    "SCSIStatus %x SCSIState %x xfercount %u\n",
47302d1d418eSSumit Saxena 		    scsi_reply->SCSIStatus, scsi_reply->SCSIState,
47312d1d418eSSumit Saxena 		    le32toh(xfer_count));
47322d1d418eSSumit Saxena 		break;
47332d1d418eSSumit Saxena 	case MPI3_IOCSTATUS_SCSI_DATA_OVERRUN:
47342d1d418eSSumit Saxena 		/* resid is ignored for this condition */
47352d1d418eSSumit Saxena 		csio->resid = 0;
47362d1d418eSSumit Saxena 		mpi3mr_set_ccbstatus(ccb, CAM_DATA_RUN_ERR);
47372d1d418eSSumit Saxena 		break;
47382d1d418eSSumit Saxena 	case MPI3_IOCSTATUS_SCSI_DATA_UNDERRUN:
47392d1d418eSSumit Saxena 		csio->resid = cm->length - le32toh(xfer_count);
47402d1d418eSSumit Saxena 	case MPI3_IOCSTATUS_SCSI_RECOVERED_ERROR:
47412d1d418eSSumit Saxena 	case MPI3_IOCSTATUS_SUCCESS:
4742baabb919SChandrakanth patil 		if ((scsi_reply->IOCStatus & MPI3_IOCSTATUS_STATUS_MASK) ==
47432d1d418eSSumit Saxena 		    MPI3_IOCSTATUS_SCSI_RECOVERED_ERROR)
47442d1d418eSSumit Saxena 			mpi3mr_dprint(sc, MPI3MR_XINFO, "func: %s line: %d recovered error\n",  __func__, __LINE__);
47452d1d418eSSumit Saxena 
47462d1d418eSSumit Saxena 		/* Completion failed at the transport level. */
47472d1d418eSSumit Saxena 		if (scsi_reply->SCSIState & (MPI3_SCSI_STATE_NO_SCSI_STATUS |
47482d1d418eSSumit Saxena 		    MPI3_SCSI_STATE_TERMINATED)) {
47492d1d418eSSumit Saxena 			mpi3mr_set_ccbstatus(ccb, CAM_REQ_CMP_ERR);
47502d1d418eSSumit Saxena 			break;
47512d1d418eSSumit Saxena 		}
47522d1d418eSSumit Saxena 
47532d1d418eSSumit Saxena 		/* In a modern packetized environment, an autosense failure
47542d1d418eSSumit Saxena 		 * implies that there's not much else that can be done to
47552d1d418eSSumit Saxena 		 * recover the command.
47562d1d418eSSumit Saxena 		 */
47572d1d418eSSumit Saxena 		if (scsi_reply->SCSIState & MPI3_SCSI_STATE_SENSE_VALID) {
47582d1d418eSSumit Saxena 			mpi3mr_set_ccbstatus(ccb, CAM_AUTOSENSE_FAIL);
47592d1d418eSSumit Saxena 			break;
47602d1d418eSSumit Saxena 		}
47612d1d418eSSumit Saxena 
47622d1d418eSSumit Saxena 		/*
47632d1d418eSSumit Saxena 		 * Intentionally override the normal SCSI status reporting
47642d1d418eSSumit Saxena 		 * for these two cases.  These are likely to happen in a
47652d1d418eSSumit Saxena 		 * multi-initiator environment, and we want to make sure that
47662d1d418eSSumit Saxena 		 * CAM retries these commands rather than fail them.
47672d1d418eSSumit Saxena 		 */
47682d1d418eSSumit Saxena 		if ((scsi_reply->SCSIStatus == MPI3_SCSI_STATUS_COMMAND_TERMINATED) ||
47692d1d418eSSumit Saxena 		    (scsi_reply->SCSIStatus == MPI3_SCSI_STATUS_TASK_ABORTED)) {
47702d1d418eSSumit Saxena 			mpi3mr_set_ccbstatus(ccb, CAM_REQ_ABORTED);
47712d1d418eSSumit Saxena 			break;
47722d1d418eSSumit Saxena 		}
47732d1d418eSSumit Saxena 
47742d1d418eSSumit Saxena 		/* Handle normal status and sense */
47752d1d418eSSumit Saxena 		csio->scsi_status = scsi_reply->SCSIStatus;
47762d1d418eSSumit Saxena 		if (scsi_reply->SCSIStatus == MPI3_SCSI_STATUS_GOOD)
47772d1d418eSSumit Saxena 			mpi3mr_set_ccbstatus(ccb, CAM_REQ_CMP);
47782d1d418eSSumit Saxena 		else
47792d1d418eSSumit Saxena 			mpi3mr_set_ccbstatus(ccb, CAM_SCSI_STATUS_ERROR);
47802d1d418eSSumit Saxena 
47812d1d418eSSumit Saxena 		if (scsi_reply->SCSIState & MPI3_SCSI_STATE_SENSE_VALID) {
47822d1d418eSSumit Saxena 			int sense_len, returned_sense_len;
47832d1d418eSSumit Saxena 
47842d1d418eSSumit Saxena 			returned_sense_len = min(le32toh(scsi_reply->SenseCount),
47852d1d418eSSumit Saxena 			    sizeof(struct scsi_sense_data));
47862d1d418eSSumit Saxena 			if (returned_sense_len < csio->sense_len)
47872d1d418eSSumit Saxena 				csio->sense_resid = csio->sense_len -
47882d1d418eSSumit Saxena 				    returned_sense_len;
47892d1d418eSSumit Saxena 			else
47902d1d418eSSumit Saxena 				csio->sense_resid = 0;
47912d1d418eSSumit Saxena 
47922d1d418eSSumit Saxena 			sense_len = min(returned_sense_len,
47932d1d418eSSumit Saxena 			    csio->sense_len - csio->sense_resid);
47942d1d418eSSumit Saxena 			bzero(&csio->sense_data, sizeof(csio->sense_data));
47952d1d418eSSumit Saxena 			bcopy(cm->sense, &csio->sense_data, sense_len);
47962d1d418eSSumit Saxena 			ccb->ccb_h.status |= CAM_AUTOSNS_VALID;
47972d1d418eSSumit Saxena 		}
47982d1d418eSSumit Saxena 
47992d1d418eSSumit Saxena 		break;
48002d1d418eSSumit Saxena 	case MPI3_IOCSTATUS_INVALID_SGL:
48012d1d418eSSumit Saxena 		mpi3mr_set_ccbstatus(ccb, CAM_UNREC_HBA_ERROR);
48022d1d418eSSumit Saxena 		break;
48032d1d418eSSumit Saxena 	case MPI3_IOCSTATUS_EEDP_GUARD_ERROR:
48042d1d418eSSumit Saxena 	case MPI3_IOCSTATUS_EEDP_REF_TAG_ERROR:
48052d1d418eSSumit Saxena 	case MPI3_IOCSTATUS_EEDP_APP_TAG_ERROR:
48062d1d418eSSumit Saxena 	case MPI3_IOCSTATUS_SCSI_PROTOCOL_ERROR:
48072d1d418eSSumit Saxena 	case MPI3_IOCSTATUS_INVALID_FUNCTION:
48082d1d418eSSumit Saxena 	case MPI3_IOCSTATUS_INTERNAL_ERROR:
48092d1d418eSSumit Saxena 	case MPI3_IOCSTATUS_INVALID_FIELD:
48102d1d418eSSumit Saxena 	case MPI3_IOCSTATUS_INVALID_STATE:
48112d1d418eSSumit Saxena 	case MPI3_IOCSTATUS_SCSI_IO_DATA_ERROR:
48122d1d418eSSumit Saxena 	case MPI3_IOCSTATUS_SCSI_TASK_MGMT_FAILED:
48132d1d418eSSumit Saxena 	case MPI3_IOCSTATUS_INSUFFICIENT_POWER:
48142d1d418eSSumit Saxena 	case MPI3_IOCSTATUS_SCSI_RESIDUAL_MISMATCH:
48152d1d418eSSumit Saxena 	default:
48162d1d418eSSumit Saxena 		csio->resid = cm->length;
48172d1d418eSSumit Saxena 		mpi3mr_set_ccbstatus(ccb, CAM_REQ_CMP_ERR);
48182d1d418eSSumit Saxena 		break;
48192d1d418eSSumit Saxena 	}
48202d1d418eSSumit Saxena 
48212d1d418eSSumit Saxena out_success:
48222d1d418eSSumit Saxena 	if (mpi3mr_get_ccbstatus(ccb) != CAM_REQ_CMP) {
48232d1d418eSSumit Saxena 		ccb->ccb_h.status |= CAM_DEV_QFRZN;
48242d1d418eSSumit Saxena 		xpt_freeze_devq(ccb->ccb_h.path, /*count*/ 1);
48252d1d418eSSumit Saxena 	}
48262d1d418eSSumit Saxena 
48272d1d418eSSumit Saxena 	mpi3mr_atomic_dec(&cm->targ->outstanding);
48282d1d418eSSumit Saxena 	mpi3mr_cmd_done(sc, cm);
48292d1d418eSSumit Saxena 	mpi3mr_dprint(sc, MPI3MR_TRACE, "Completion IO path :"
48302d1d418eSSumit Saxena 		" cdb[0]: %x targetid: 0x%x SMID: %x ioc_status: 0x%x ioc_loginfo: 0x%x scsi_status: 0x%x "
48312d1d418eSSumit Saxena 		"scsi_state: 0x%x response_data: 0x%x\n", scsi_cdb[0], target_id, host_tag,
48322d1d418eSSumit Saxena 		ioc_status, ioc_loginfo, scsi_status, scsi_state, resp_data);
48332d1d418eSSumit Saxena 	mpi3mr_atomic_dec(&sc->fw_outstanding);
48342d1d418eSSumit Saxena out:
48352d1d418eSSumit Saxena 
48362d1d418eSSumit Saxena 	if (sense_buf)
48372d1d418eSSumit Saxena 		mpi3mr_repost_sense_buf(sc,
48382d1d418eSSumit Saxena 		    scsi_reply->SenseDataBufferAddress);
48392d1d418eSSumit Saxena 	return;
48402d1d418eSSumit Saxena }
48412d1d418eSSumit Saxena 
48422d1d418eSSumit Saxena /*
48432d1d418eSSumit Saxena  * mpi3mr_complete_io_cmd:	ISR routine for IO commands
48442d1d418eSSumit Saxena  * @sc:				Adapter's soft instance
48452d1d418eSSumit Saxena  * @irq_ctx:			Driver's internal per IRQ structure
48462d1d418eSSumit Saxena  *
48472d1d418eSSumit Saxena  * This function processes IO command completions.
48482d1d418eSSumit Saxena  */
mpi3mr_complete_io_cmd(struct mpi3mr_softc * sc,struct mpi3mr_irq_context * irq_ctx)48492d1d418eSSumit Saxena int mpi3mr_complete_io_cmd(struct mpi3mr_softc *sc,
48502d1d418eSSumit Saxena     struct mpi3mr_irq_context *irq_ctx)
48512d1d418eSSumit Saxena {
48522d1d418eSSumit Saxena 	struct mpi3mr_op_reply_queue *op_reply_q = irq_ctx->op_reply_q;
48532d1d418eSSumit Saxena 	U32 exp_phase = op_reply_q->ephase;
48542d1d418eSSumit Saxena 	U32 reply_ci = op_reply_q->ci;
48552d1d418eSSumit Saxena 	U32 num_op_replies = 0;
48562d1d418eSSumit Saxena 	U64 reply_dma = 0;
48572d1d418eSSumit Saxena 	Mpi3DefaultReplyDescriptor_t *reply_desc;
4858eb7a4b35SChandrakanth patil 	U16 req_qid = 0, threshold_comps = 0;
48592d1d418eSSumit Saxena 
48602d1d418eSSumit Saxena 	mtx_lock_spin(&op_reply_q->q_lock);
48612d1d418eSSumit Saxena 	if (op_reply_q->in_use == false) {
48622d1d418eSSumit Saxena 		op_reply_q->in_use = true;
48632d1d418eSSumit Saxena 		mtx_unlock_spin(&op_reply_q->q_lock);
48642d1d418eSSumit Saxena 	} else {
48652d1d418eSSumit Saxena 		mtx_unlock_spin(&op_reply_q->q_lock);
48662d1d418eSSumit Saxena 		return 0;
48672d1d418eSSumit Saxena 	}
48682d1d418eSSumit Saxena 
48692d1d418eSSumit Saxena 	reply_desc = (Mpi3DefaultReplyDescriptor_t *)op_reply_q->q_base + reply_ci;
48702d1d418eSSumit Saxena 	mpi3mr_dprint(sc, MPI3MR_TRACE, "[QID:%d]:reply_desc: (%pa) reply_ci: %x"
48712d1d418eSSumit Saxena 		" reply_desc->ReplyFlags: 0x%x\n"
48722d1d418eSSumit Saxena 		"reply_q_base_phys: %#016jx reply_q_base: (%pa) exp_phase: %x\n",
48732d1d418eSSumit Saxena 		op_reply_q->qid, reply_desc, reply_ci, reply_desc->ReplyFlags, op_reply_q->q_base_phys,
48742d1d418eSSumit Saxena 		op_reply_q->q_base, exp_phase);
48752d1d418eSSumit Saxena 
48762d1d418eSSumit Saxena 	if (((reply_desc->ReplyFlags &
48772d1d418eSSumit Saxena 	     MPI3_REPLY_DESCRIPT_FLAGS_PHASE_MASK) != exp_phase) || !op_reply_q->qid) {
48782d1d418eSSumit Saxena 		mtx_lock_spin(&op_reply_q->q_lock);
48792d1d418eSSumit Saxena 		op_reply_q->in_use = false;
48802d1d418eSSumit Saxena 		mtx_unlock_spin(&op_reply_q->q_lock);
48812d1d418eSSumit Saxena 		return 0;
48822d1d418eSSumit Saxena 	}
48832d1d418eSSumit Saxena 
48842d1d418eSSumit Saxena 	do {
48852d1d418eSSumit Saxena 		req_qid = reply_desc->RequestQueueID;
48862d1d418eSSumit Saxena 		sc->op_req_q[req_qid - 1].ci =
48872d1d418eSSumit Saxena 		    reply_desc->RequestQueueCI;
48882d1d418eSSumit Saxena 
48892d1d418eSSumit Saxena 		mpi3mr_process_op_reply_desc(sc, reply_desc, &reply_dma);
48902d1d418eSSumit Saxena 		mpi3mr_atomic_dec(&op_reply_q->pend_ios);
48912d1d418eSSumit Saxena 		if (reply_dma)
48922d1d418eSSumit Saxena 			mpi3mr_repost_reply_buf(sc, reply_dma);
48932d1d418eSSumit Saxena 		num_op_replies++;
48942d1d418eSSumit Saxena 		if (++reply_ci == op_reply_q->num_replies) {
48952d1d418eSSumit Saxena 			reply_ci = 0;
48962d1d418eSSumit Saxena 			exp_phase ^= 1;
48972d1d418eSSumit Saxena 		}
48982d1d418eSSumit Saxena 		reply_desc =
48992d1d418eSSumit Saxena 		    (Mpi3DefaultReplyDescriptor_t *)op_reply_q->q_base + reply_ci;
49002d1d418eSSumit Saxena 		if ((reply_desc->ReplyFlags &
49012d1d418eSSumit Saxena 		     MPI3_REPLY_DESCRIPT_FLAGS_PHASE_MASK) != exp_phase)
49022d1d418eSSumit Saxena 			break;
4903eb7a4b35SChandrakanth patil 
4904eb7a4b35SChandrakanth patil 		if (++threshold_comps == MPI3MR_THRESHOLD_REPLY_COUNT) {
4905eb7a4b35SChandrakanth patil 			mpi3mr_regwrite(sc, MPI3_SYSIF_OPER_REPLY_Q_N_CI_OFFSET(op_reply_q->qid), reply_ci);
4906eb7a4b35SChandrakanth patil 			threshold_comps = 0;
4907eb7a4b35SChandrakanth patil 		}
4908eb7a4b35SChandrakanth patil 
49092d1d418eSSumit Saxena 	} while (1);
49102d1d418eSSumit Saxena 
49112d1d418eSSumit Saxena 
49122d1d418eSSumit Saxena 	mpi3mr_regwrite(sc, MPI3_SYSIF_OPER_REPLY_Q_N_CI_OFFSET(op_reply_q->qid), reply_ci);
49132d1d418eSSumit Saxena 	op_reply_q->ci = reply_ci;
49142d1d418eSSumit Saxena 	op_reply_q->ephase = exp_phase;
49152d1d418eSSumit Saxena 	mtx_lock_spin(&op_reply_q->q_lock);
49162d1d418eSSumit Saxena 	op_reply_q->in_use = false;
49172d1d418eSSumit Saxena 	mtx_unlock_spin(&op_reply_q->q_lock);
49182d1d418eSSumit Saxena 	return num_op_replies;
49192d1d418eSSumit Saxena }
49202d1d418eSSumit Saxena 
49212d1d418eSSumit Saxena /*
49222d1d418eSSumit Saxena  * mpi3mr_isr:			Primary ISR function
49232d1d418eSSumit Saxena  * privdata:			Driver's internal per IRQ structure
49242d1d418eSSumit Saxena  *
49252d1d418eSSumit Saxena  * This is driver's primary ISR function which is being called whenever any admin/IO
49262d1d418eSSumit Saxena  * command completion.
49272d1d418eSSumit Saxena  */
mpi3mr_isr(void * privdata)49282d1d418eSSumit Saxena void mpi3mr_isr(void *privdata)
49292d1d418eSSumit Saxena {
49302d1d418eSSumit Saxena 	struct mpi3mr_irq_context *irq_ctx = (struct mpi3mr_irq_context *)privdata;
49312d1d418eSSumit Saxena 	struct mpi3mr_softc *sc = irq_ctx->sc;
49322d1d418eSSumit Saxena 	U16 msi_idx;
49332d1d418eSSumit Saxena 
49342d1d418eSSumit Saxena 	if (!irq_ctx)
49352d1d418eSSumit Saxena 		return;
49362d1d418eSSumit Saxena 
49372d1d418eSSumit Saxena 	msi_idx = irq_ctx->msix_index;
49382d1d418eSSumit Saxena 
49392d1d418eSSumit Saxena 	if (!sc->intr_enabled)
49402d1d418eSSumit Saxena 		return;
49412d1d418eSSumit Saxena 
49422d1d418eSSumit Saxena 	if (!msi_idx)
49432d1d418eSSumit Saxena 		mpi3mr_complete_admin_cmd(sc);
49442d1d418eSSumit Saxena 
49452d1d418eSSumit Saxena 	if (irq_ctx->op_reply_q && irq_ctx->op_reply_q->qid) {
49462d1d418eSSumit Saxena 		mpi3mr_complete_io_cmd(sc, irq_ctx);
49472d1d418eSSumit Saxena 	}
49482d1d418eSSumit Saxena }
49492d1d418eSSumit Saxena 
49502d1d418eSSumit Saxena /*
49512d1d418eSSumit Saxena  * mpi3mr_alloc_requests - Allocates host commands
49522d1d418eSSumit Saxena  * @sc: Adapter reference
49532d1d418eSSumit Saxena  *
49542d1d418eSSumit Saxena  * This function allocates controller supported host commands
49552d1d418eSSumit Saxena  *
49562d1d418eSSumit Saxena  * Return: 0 on success and proper error codes on failure
49572d1d418eSSumit Saxena  */
49582d1d418eSSumit Saxena int
mpi3mr_alloc_requests(struct mpi3mr_softc * sc)49592d1d418eSSumit Saxena mpi3mr_alloc_requests(struct mpi3mr_softc *sc)
49602d1d418eSSumit Saxena {
49612d1d418eSSumit Saxena 	struct mpi3mr_cmd *cmd;
49622d1d418eSSumit Saxena 	int i, j, nsegs, ret;
49632d1d418eSSumit Saxena 
49642d1d418eSSumit Saxena 	nsegs = MPI3MR_SG_DEPTH;
49652d1d418eSSumit Saxena 	ret = bus_dma_tag_create( sc->mpi3mr_parent_dmat,    /* parent */
49662d1d418eSSumit Saxena 				1, 0,			/* algnmnt, boundary */
4967ee7c431cSWarner Losh 				sc->dma_loaddr,		/* lowaddr */
49681ec7c672SWarner Losh 				BUS_SPACE_MAXADDR,	/* highaddr */
49692d1d418eSSumit Saxena 				NULL, NULL,		/* filter, filterarg */
49704e6d128bSAlexander Motin 				BUS_SPACE_MAXSIZE,	/* maxsize */
49712d1d418eSSumit Saxena                                 nsegs,			/* nsegments */
49724e6d128bSAlexander Motin 				BUS_SPACE_MAXSIZE_32BIT,/* maxsegsize */
49732d1d418eSSumit Saxena                                 BUS_DMA_ALLOCNOW,	/* flags */
49742d1d418eSSumit Saxena                                 busdma_lock_mutex,	/* lockfunc */
49752d1d418eSSumit Saxena 				&sc->io_lock,	/* lockarg */
49762d1d418eSSumit Saxena 				&sc->buffer_dmat);
49772d1d418eSSumit Saxena 	if (ret) {
49782d1d418eSSumit Saxena 		mpi3mr_dprint(sc, MPI3MR_ERROR, "Cannot allocate buffer DMA tag ret: %d\n", ret);
49792d1d418eSSumit Saxena 		return (ENOMEM);
49802d1d418eSSumit Saxena         }
49812d1d418eSSumit Saxena 
49822d1d418eSSumit Saxena 	/*
49832d1d418eSSumit Saxena 	 * sc->cmd_list is an array of struct mpi3mr_cmd pointers.
49842d1d418eSSumit Saxena 	 * Allocate the dynamic array first and then allocate individual
49852d1d418eSSumit Saxena 	 * commands.
49862d1d418eSSumit Saxena 	 */
49872d1d418eSSumit Saxena 	sc->cmd_list = malloc(sizeof(struct mpi3mr_cmd *) * sc->max_host_ios,
49882d1d418eSSumit Saxena 	    M_MPI3MR, M_NOWAIT | M_ZERO);
49892d1d418eSSumit Saxena 
49902d1d418eSSumit Saxena 	if (!sc->cmd_list) {
49912d1d418eSSumit Saxena 		device_printf(sc->mpi3mr_dev, "Cannot alloc memory for mpt_cmd_list.\n");
49922d1d418eSSumit Saxena 		return (ENOMEM);
49932d1d418eSSumit Saxena 	}
49942d1d418eSSumit Saxena 
49952d1d418eSSumit Saxena 	for (i = 0; i < sc->max_host_ios; i++) {
49962d1d418eSSumit Saxena 		sc->cmd_list[i] = malloc(sizeof(struct mpi3mr_cmd),
49972d1d418eSSumit Saxena 		    M_MPI3MR, M_NOWAIT | M_ZERO);
49982d1d418eSSumit Saxena 		if (!sc->cmd_list[i]) {
49992d1d418eSSumit Saxena 			for (j = 0; j < i; j++)
50002d1d418eSSumit Saxena 				free(sc->cmd_list[j], M_MPI3MR);
50012d1d418eSSumit Saxena 			free(sc->cmd_list, M_MPI3MR);
50022d1d418eSSumit Saxena 			sc->cmd_list = NULL;
50032d1d418eSSumit Saxena 			return (ENOMEM);
50042d1d418eSSumit Saxena 		}
50052d1d418eSSumit Saxena 	}
50062d1d418eSSumit Saxena 
50072d1d418eSSumit Saxena 	for (i = 1; i < sc->max_host_ios; i++) {
50082d1d418eSSumit Saxena 		cmd = sc->cmd_list[i];
50092d1d418eSSumit Saxena 		cmd->hosttag = i;
50102d1d418eSSumit Saxena 		cmd->sc = sc;
50112d1d418eSSumit Saxena 		cmd->state = MPI3MR_CMD_STATE_BUSY;
50122d1d418eSSumit Saxena 		callout_init_mtx(&cmd->callout, &sc->mpi3mr_mtx, 0);
50132d1d418eSSumit Saxena 		cmd->ccb = NULL;
50142d1d418eSSumit Saxena 		TAILQ_INSERT_TAIL(&(sc->cmd_list_head), cmd, next);
50152d1d418eSSumit Saxena 		if (bus_dmamap_create(sc->buffer_dmat, 0, &cmd->dmamap))
50162d1d418eSSumit Saxena 			return ENOMEM;
50172d1d418eSSumit Saxena 	}
50182d1d418eSSumit Saxena 	return (0);
50192d1d418eSSumit Saxena }
50202d1d418eSSumit Saxena 
50212d1d418eSSumit Saxena /*
50222d1d418eSSumit Saxena  * mpi3mr_get_command:		Get a coomand structure from free command pool
50232d1d418eSSumit Saxena  * @sc:				Adapter soft instance
50242d1d418eSSumit Saxena  * Return:			MPT command reference
50252d1d418eSSumit Saxena  *
50262d1d418eSSumit Saxena  * This function returns an MPT command to the caller.
50272d1d418eSSumit Saxena  */
50282d1d418eSSumit Saxena struct mpi3mr_cmd *
mpi3mr_get_command(struct mpi3mr_softc * sc)50292d1d418eSSumit Saxena mpi3mr_get_command(struct mpi3mr_softc *sc)
50302d1d418eSSumit Saxena {
50312d1d418eSSumit Saxena 	struct mpi3mr_cmd *cmd = NULL;
50322d1d418eSSumit Saxena 
50332d1d418eSSumit Saxena 	mtx_lock(&sc->cmd_pool_lock);
50342d1d418eSSumit Saxena 	if (!TAILQ_EMPTY(&sc->cmd_list_head)) {
50352d1d418eSSumit Saxena 		cmd = TAILQ_FIRST(&sc->cmd_list_head);
50362d1d418eSSumit Saxena 		TAILQ_REMOVE(&sc->cmd_list_head, cmd, next);
50372d1d418eSSumit Saxena 	} else {
50382d1d418eSSumit Saxena 		goto out;
50392d1d418eSSumit Saxena 	}
50402d1d418eSSumit Saxena 
50412d1d418eSSumit Saxena 	mpi3mr_dprint(sc, MPI3MR_TRACE, "Get command SMID: 0x%x\n", cmd->hosttag);
50422d1d418eSSumit Saxena 
50432d1d418eSSumit Saxena 	memset((uint8_t *)&cmd->io_request, 0, MPI3MR_AREQ_FRAME_SZ);
50442d1d418eSSumit Saxena 	cmd->data_dir = 0;
50452d1d418eSSumit Saxena 	cmd->ccb = NULL;
50462d1d418eSSumit Saxena 	cmd->targ = NULL;
50472d1d418eSSumit Saxena 	cmd->state = MPI3MR_CMD_STATE_BUSY;
50482d1d418eSSumit Saxena 	cmd->data = NULL;
50492d1d418eSSumit Saxena 	cmd->length = 0;
50502d1d418eSSumit Saxena out:
50512d1d418eSSumit Saxena 	mtx_unlock(&sc->cmd_pool_lock);
50522d1d418eSSumit Saxena 	return cmd;
50532d1d418eSSumit Saxena }
50542d1d418eSSumit Saxena 
50552d1d418eSSumit Saxena /*
50562d1d418eSSumit Saxena  * mpi3mr_release_command:	Return a cmd to free command pool
50572d1d418eSSumit Saxena  * input:			Command packet for return to free command pool
50582d1d418eSSumit Saxena  *
50592d1d418eSSumit Saxena  * This function returns an MPT command to the free command list.
50602d1d418eSSumit Saxena  */
50612d1d418eSSumit Saxena void
mpi3mr_release_command(struct mpi3mr_cmd * cmd)50622d1d418eSSumit Saxena mpi3mr_release_command(struct mpi3mr_cmd *cmd)
50632d1d418eSSumit Saxena {
50642d1d418eSSumit Saxena 	struct mpi3mr_softc *sc = cmd->sc;
50652d1d418eSSumit Saxena 
50662d1d418eSSumit Saxena 	mtx_lock(&sc->cmd_pool_lock);
50672d1d418eSSumit Saxena 	TAILQ_INSERT_HEAD(&(sc->cmd_list_head), cmd, next);
50682d1d418eSSumit Saxena 	cmd->state = MPI3MR_CMD_STATE_FREE;
50692d1d418eSSumit Saxena 	cmd->req_qidx = 0;
50702d1d418eSSumit Saxena 	mpi3mr_dprint(sc, MPI3MR_TRACE, "Release command SMID: 0x%x\n", cmd->hosttag);
50712d1d418eSSumit Saxena 	mtx_unlock(&sc->cmd_pool_lock);
50722d1d418eSSumit Saxena 
50732d1d418eSSumit Saxena 	return;
50742d1d418eSSumit Saxena }
50752d1d418eSSumit Saxena 
50762d1d418eSSumit Saxena  /**
50772d1d418eSSumit Saxena  * mpi3mr_free_ioctl_dma_memory - free memory for ioctl dma
50782d1d418eSSumit Saxena  * @sc: Adapter instance reference
50792d1d418eSSumit Saxena  *
50802d1d418eSSumit Saxena  * Free the DMA memory allocated for IOCTL handling purpose.
50812d1d418eSSumit Saxena  *
50822d1d418eSSumit Saxena  * Return: None
50832d1d418eSSumit Saxena  */
mpi3mr_free_ioctl_dma_memory(struct mpi3mr_softc * sc)50842d1d418eSSumit Saxena static void mpi3mr_free_ioctl_dma_memory(struct mpi3mr_softc *sc)
50852d1d418eSSumit Saxena {
50862d1d418eSSumit Saxena 	U16 i;
50872d1d418eSSumit Saxena 	struct dma_memory_desc *mem_desc;
50882d1d418eSSumit Saxena 
50892d1d418eSSumit Saxena 	for (i=0; i<MPI3MR_NUM_IOCTL_SGE; i++) {
50902d1d418eSSumit Saxena 		mem_desc = &sc->ioctl_sge[i];
50912d1d418eSSumit Saxena 		if (mem_desc->addr && mem_desc->dma_addr) {
50922d1d418eSSumit Saxena 			bus_dmamap_unload(mem_desc->tag, mem_desc->dmamap);
50932d1d418eSSumit Saxena 			bus_dmamem_free(mem_desc->tag, mem_desc->addr, mem_desc->dmamap);
50942d1d418eSSumit Saxena 			mem_desc->addr = NULL;
50952d1d418eSSumit Saxena 			if (mem_desc->tag != NULL)
50962d1d418eSSumit Saxena 				bus_dma_tag_destroy(mem_desc->tag);
50972d1d418eSSumit Saxena 		}
50982d1d418eSSumit Saxena 	}
50992d1d418eSSumit Saxena 
51002d1d418eSSumit Saxena 	mem_desc = &sc->ioctl_chain_sge;
51012d1d418eSSumit Saxena 	if (mem_desc->addr && mem_desc->dma_addr) {
51022d1d418eSSumit Saxena 		bus_dmamap_unload(mem_desc->tag, mem_desc->dmamap);
51032d1d418eSSumit Saxena 		bus_dmamem_free(mem_desc->tag, mem_desc->addr, mem_desc->dmamap);
51042d1d418eSSumit Saxena 		mem_desc->addr = NULL;
51052d1d418eSSumit Saxena 		if (mem_desc->tag != NULL)
51062d1d418eSSumit Saxena 			bus_dma_tag_destroy(mem_desc->tag);
51072d1d418eSSumit Saxena 	}
51082d1d418eSSumit Saxena 
51092d1d418eSSumit Saxena 	mem_desc = &sc->ioctl_resp_sge;
51102d1d418eSSumit Saxena 	if (mem_desc->addr && mem_desc->dma_addr) {
51112d1d418eSSumit Saxena 		bus_dmamap_unload(mem_desc->tag, mem_desc->dmamap);
51122d1d418eSSumit Saxena 		bus_dmamem_free(mem_desc->tag, mem_desc->addr, mem_desc->dmamap);
51132d1d418eSSumit Saxena 		mem_desc->addr = NULL;
51142d1d418eSSumit Saxena 		if (mem_desc->tag != NULL)
51152d1d418eSSumit Saxena 			bus_dma_tag_destroy(mem_desc->tag);
51162d1d418eSSumit Saxena 	}
51172d1d418eSSumit Saxena 
51182d1d418eSSumit Saxena 	sc->ioctl_sges_allocated = false;
51192d1d418eSSumit Saxena }
51202d1d418eSSumit Saxena 
51212d1d418eSSumit Saxena /**
51222d1d418eSSumit Saxena  * mpi3mr_alloc_ioctl_dma_memory - Alloc memory for ioctl dma
51232d1d418eSSumit Saxena  * @sc: Adapter instance reference
51242d1d418eSSumit Saxena  *
51252d1d418eSSumit Saxena  * This function allocates dmaable memory required to handle the
51262d1d418eSSumit Saxena  * application issued MPI3 IOCTL requests.
51272d1d418eSSumit Saxena  *
51282d1d418eSSumit Saxena  * Return: None
51292d1d418eSSumit Saxena  */
mpi3mr_alloc_ioctl_dma_memory(struct mpi3mr_softc * sc)51302d1d418eSSumit Saxena void mpi3mr_alloc_ioctl_dma_memory(struct mpi3mr_softc *sc)
51312d1d418eSSumit Saxena {
51322d1d418eSSumit Saxena 	struct dma_memory_desc *mem_desc;
51332d1d418eSSumit Saxena 	U16 i;
51342d1d418eSSumit Saxena 
51352d1d418eSSumit Saxena 	for (i=0; i<MPI3MR_NUM_IOCTL_SGE; i++) {
51362d1d418eSSumit Saxena 		mem_desc = &sc->ioctl_sge[i];
51372d1d418eSSumit Saxena 		mem_desc->size = MPI3MR_IOCTL_SGE_SIZE;
51382d1d418eSSumit Saxena 
51392d1d418eSSumit Saxena 		if (bus_dma_tag_create(sc->mpi3mr_parent_dmat,    /* parent */
51402d1d418eSSumit Saxena 					4, 0,			/* algnmnt, boundary */
5141ee7c431cSWarner Losh 					sc->dma_loaddr,		/* lowaddr */
51421ec7c672SWarner Losh 					BUS_SPACE_MAXADDR,	/* highaddr */
51432d1d418eSSumit Saxena 					NULL, NULL,		/* filter, filterarg */
51442d1d418eSSumit Saxena 					mem_desc->size,		/* maxsize */
51452d1d418eSSumit Saxena 					1,			/* nsegments */
51462d1d418eSSumit Saxena 					mem_desc->size,		/* maxsegsize */
51472d1d418eSSumit Saxena 					0,			/* flags */
51482d1d418eSSumit Saxena 					NULL, NULL,		/* lockfunc, lockarg */
51492d1d418eSSumit Saxena 					&mem_desc->tag)) {
51502d1d418eSSumit Saxena 			mpi3mr_dprint(sc, MPI3MR_ERROR, "Cannot allocate request DMA tag\n");
51512d1d418eSSumit Saxena 			goto out_failed;
51522d1d418eSSumit Saxena 		}
51532d1d418eSSumit Saxena 
51542d1d418eSSumit Saxena 		if (bus_dmamem_alloc(mem_desc->tag, (void **)&mem_desc->addr,
51552d1d418eSSumit Saxena 		    BUS_DMA_NOWAIT, &mem_desc->dmamap)) {
5156ee7c431cSWarner Losh 			mpi3mr_dprint(sc, MPI3MR_ERROR, "%s: Cannot allocate replies memory\n", __func__);
51572d1d418eSSumit Saxena 			goto out_failed;
51582d1d418eSSumit Saxena 		}
51592d1d418eSSumit Saxena 		bzero(mem_desc->addr, mem_desc->size);
51602d1d418eSSumit Saxena 		bus_dmamap_load(mem_desc->tag, mem_desc->dmamap, mem_desc->addr, mem_desc->size,
516139a3e6a8SAlexander Motin 		    mpi3mr_memaddr_cb, &mem_desc->dma_addr, BUS_DMA_NOWAIT);
51622d1d418eSSumit Saxena 
51632d1d418eSSumit Saxena 		if (!mem_desc->addr)
51642d1d418eSSumit Saxena 			goto out_failed;
51652d1d418eSSumit Saxena 	}
51662d1d418eSSumit Saxena 
51672d1d418eSSumit Saxena 	mem_desc = &sc->ioctl_chain_sge;
51682d1d418eSSumit Saxena 	mem_desc->size = MPI3MR_4K_PGSZ;
51692d1d418eSSumit Saxena 	if (bus_dma_tag_create(sc->mpi3mr_parent_dmat,    /* parent */
51702d1d418eSSumit Saxena 				4, 0,			/* algnmnt, boundary */
5171ee7c431cSWarner Losh 				sc->dma_loaddr,		/* lowaddr */
51721ec7c672SWarner Losh 				BUS_SPACE_MAXADDR,	/* highaddr */
51732d1d418eSSumit Saxena 				NULL, NULL,		/* filter, filterarg */
51742d1d418eSSumit Saxena 				mem_desc->size,		/* maxsize */
51752d1d418eSSumit Saxena 				1,			/* nsegments */
51762d1d418eSSumit Saxena 				mem_desc->size,		/* maxsegsize */
51772d1d418eSSumit Saxena 				0,			/* flags */
51782d1d418eSSumit Saxena 				NULL, NULL,		/* lockfunc, lockarg */
51792d1d418eSSumit Saxena 				&mem_desc->tag)) {
51802d1d418eSSumit Saxena 		mpi3mr_dprint(sc, MPI3MR_ERROR, "Cannot allocate request DMA tag\n");
51812d1d418eSSumit Saxena 		goto out_failed;
51822d1d418eSSumit Saxena 	}
51832d1d418eSSumit Saxena 
51842d1d418eSSumit Saxena 	if (bus_dmamem_alloc(mem_desc->tag, (void **)&mem_desc->addr,
51852d1d418eSSumit Saxena 	    BUS_DMA_NOWAIT, &mem_desc->dmamap)) {
5186ee7c431cSWarner Losh 		mpi3mr_dprint(sc, MPI3MR_ERROR, "%s: Cannot allocate replies memory\n", __func__);
51872d1d418eSSumit Saxena 		goto out_failed;
51882d1d418eSSumit Saxena 	}
51892d1d418eSSumit Saxena 	bzero(mem_desc->addr, mem_desc->size);
51902d1d418eSSumit Saxena 	bus_dmamap_load(mem_desc->tag, mem_desc->dmamap, mem_desc->addr, mem_desc->size,
519139a3e6a8SAlexander Motin 	    mpi3mr_memaddr_cb, &mem_desc->dma_addr, BUS_DMA_NOWAIT);
51922d1d418eSSumit Saxena 
51932d1d418eSSumit Saxena 	if (!mem_desc->addr)
51942d1d418eSSumit Saxena 		goto out_failed;
51952d1d418eSSumit Saxena 
51962d1d418eSSumit Saxena 	mem_desc = &sc->ioctl_resp_sge;
51972d1d418eSSumit Saxena 	mem_desc->size = MPI3MR_4K_PGSZ;
51982d1d418eSSumit Saxena 	if (bus_dma_tag_create(sc->mpi3mr_parent_dmat,    /* parent */
51992d1d418eSSumit Saxena 				4, 0,			/* algnmnt, boundary */
5200ee7c431cSWarner Losh 				sc->dma_loaddr,		/* lowaddr */
52011ec7c672SWarner Losh 				BUS_SPACE_MAXADDR,	/* highaddr */
52022d1d418eSSumit Saxena 				NULL, NULL,		/* filter, filterarg */
52032d1d418eSSumit Saxena 				mem_desc->size,		/* maxsize */
52042d1d418eSSumit Saxena 				1,			/* nsegments */
52052d1d418eSSumit Saxena 				mem_desc->size,		/* maxsegsize */
52062d1d418eSSumit Saxena 				0,			/* flags */
52072d1d418eSSumit Saxena 				NULL, NULL,		/* lockfunc, lockarg */
52082d1d418eSSumit Saxena 				&mem_desc->tag)) {
52092d1d418eSSumit Saxena 		mpi3mr_dprint(sc, MPI3MR_ERROR, "Cannot allocate request DMA tag\n");
52102d1d418eSSumit Saxena 		goto out_failed;
52112d1d418eSSumit Saxena 	}
52122d1d418eSSumit Saxena 
52132d1d418eSSumit Saxena 	if (bus_dmamem_alloc(mem_desc->tag, (void **)&mem_desc->addr,
52142d1d418eSSumit Saxena 	    BUS_DMA_NOWAIT, &mem_desc->dmamap)) {
52152d1d418eSSumit Saxena 		mpi3mr_dprint(sc, MPI3MR_ERROR, "Cannot allocate replies memory\n");
52162d1d418eSSumit Saxena 		goto out_failed;
52172d1d418eSSumit Saxena 	}
52182d1d418eSSumit Saxena 	bzero(mem_desc->addr, mem_desc->size);
52192d1d418eSSumit Saxena 	bus_dmamap_load(mem_desc->tag, mem_desc->dmamap, mem_desc->addr, mem_desc->size,
522039a3e6a8SAlexander Motin 	    mpi3mr_memaddr_cb, &mem_desc->dma_addr, BUS_DMA_NOWAIT);
52212d1d418eSSumit Saxena 
52222d1d418eSSumit Saxena 	if (!mem_desc->addr)
52232d1d418eSSumit Saxena 		goto out_failed;
52242d1d418eSSumit Saxena 
52252d1d418eSSumit Saxena 	sc->ioctl_sges_allocated = true;
52262d1d418eSSumit Saxena 
52272d1d418eSSumit Saxena 	return;
52282d1d418eSSumit Saxena out_failed:
52292d1d418eSSumit Saxena 	printf("cannot allocate DMA memory for the mpt commands"
52302d1d418eSSumit Saxena 	    "  from the applications, application interface for MPT command is disabled\n");
52312d1d418eSSumit Saxena 	mpi3mr_free_ioctl_dma_memory(sc);
52322d1d418eSSumit Saxena }
52332d1d418eSSumit Saxena 
52342d1d418eSSumit Saxena void
mpi3mr_destory_mtx(struct mpi3mr_softc * sc)52352d1d418eSSumit Saxena mpi3mr_destory_mtx(struct mpi3mr_softc *sc)
52362d1d418eSSumit Saxena {
52372d1d418eSSumit Saxena 	int i;
52382d1d418eSSumit Saxena 	struct mpi3mr_op_req_queue *op_req_q;
52392d1d418eSSumit Saxena 	struct mpi3mr_op_reply_queue *op_reply_q;
52402d1d418eSSumit Saxena 
52412d1d418eSSumit Saxena 	if (sc->admin_reply) {
52422d1d418eSSumit Saxena 		if (mtx_initialized(&sc->admin_reply_lock))
52432d1d418eSSumit Saxena 			mtx_destroy(&sc->admin_reply_lock);
52442d1d418eSSumit Saxena 	}
52452d1d418eSSumit Saxena 
52462d1d418eSSumit Saxena 	if (sc->op_reply_q) {
52472d1d418eSSumit Saxena 		for(i = 0; i < sc->num_queues; i++) {
52482d1d418eSSumit Saxena 			op_reply_q = sc->op_reply_q + i;
52492d1d418eSSumit Saxena 			if (mtx_initialized(&op_reply_q->q_lock))
52502d1d418eSSumit Saxena 				mtx_destroy(&op_reply_q->q_lock);
52512d1d418eSSumit Saxena 		}
52522d1d418eSSumit Saxena 	}
52532d1d418eSSumit Saxena 
52542d1d418eSSumit Saxena 	if (sc->op_req_q) {
52552d1d418eSSumit Saxena 		for(i = 0; i < sc->num_queues; i++) {
52562d1d418eSSumit Saxena 			op_req_q = sc->op_req_q + i;
52572d1d418eSSumit Saxena 			if (mtx_initialized(&op_req_q->q_lock))
52582d1d418eSSumit Saxena 				mtx_destroy(&op_req_q->q_lock);
52592d1d418eSSumit Saxena 		}
52602d1d418eSSumit Saxena 	}
52612d1d418eSSumit Saxena 
52622d1d418eSSumit Saxena 	if (mtx_initialized(&sc->init_cmds.completion.lock))
52632d1d418eSSumit Saxena 		mtx_destroy(&sc->init_cmds.completion.lock);
52642d1d418eSSumit Saxena 
52652d1d418eSSumit Saxena 	if (mtx_initialized(&sc->ioctl_cmds.completion.lock))
52662d1d418eSSumit Saxena 		mtx_destroy(&sc->ioctl_cmds.completion.lock);
52672d1d418eSSumit Saxena 
52682d1d418eSSumit Saxena 	if (mtx_initialized(&sc->host_tm_cmds.completion.lock))
52692d1d418eSSumit Saxena 		mtx_destroy(&sc->host_tm_cmds.completion.lock);
52702d1d418eSSumit Saxena 
52712d1d418eSSumit Saxena 	for (i = 0; i < MPI3MR_NUM_DEVRMCMD; i++) {
52722d1d418eSSumit Saxena 		if (mtx_initialized(&sc->dev_rmhs_cmds[i].completion.lock))
52732d1d418eSSumit Saxena 			mtx_destroy(&sc->dev_rmhs_cmds[i].completion.lock);
52742d1d418eSSumit Saxena 	}
52752d1d418eSSumit Saxena 
52762d1d418eSSumit Saxena 	if (mtx_initialized(&sc->reset_mutex))
52772d1d418eSSumit Saxena 		mtx_destroy(&sc->reset_mutex);
52782d1d418eSSumit Saxena 
52792d1d418eSSumit Saxena 	if (mtx_initialized(&sc->target_lock))
52802d1d418eSSumit Saxena 		mtx_destroy(&sc->target_lock);
52812d1d418eSSumit Saxena 
52822d1d418eSSumit Saxena 	if (mtx_initialized(&sc->fwevt_lock))
52832d1d418eSSumit Saxena 		mtx_destroy(&sc->fwevt_lock);
52842d1d418eSSumit Saxena 
52852d1d418eSSumit Saxena 	if (mtx_initialized(&sc->cmd_pool_lock))
52862d1d418eSSumit Saxena 		mtx_destroy(&sc->cmd_pool_lock);
52872d1d418eSSumit Saxena 
52882d1d418eSSumit Saxena 	if (mtx_initialized(&sc->reply_free_q_lock))
52892d1d418eSSumit Saxena 		mtx_destroy(&sc->reply_free_q_lock);
52902d1d418eSSumit Saxena 
52912d1d418eSSumit Saxena 	if (mtx_initialized(&sc->sense_buf_q_lock))
52922d1d418eSSumit Saxena 		mtx_destroy(&sc->sense_buf_q_lock);
52932d1d418eSSumit Saxena 
52942d1d418eSSumit Saxena 	if (mtx_initialized(&sc->chain_buf_lock))
52952d1d418eSSumit Saxena 		mtx_destroy(&sc->chain_buf_lock);
52962d1d418eSSumit Saxena 
52972d1d418eSSumit Saxena 	if (mtx_initialized(&sc->admin_req_lock))
52982d1d418eSSumit Saxena 		mtx_destroy(&sc->admin_req_lock);
52992d1d418eSSumit Saxena 
53002d1d418eSSumit Saxena 	if (mtx_initialized(&sc->mpi3mr_mtx))
53012d1d418eSSumit Saxena 		mtx_destroy(&sc->mpi3mr_mtx);
53022d1d418eSSumit Saxena }
53032d1d418eSSumit Saxena 
53042d1d418eSSumit Saxena /**
53052d1d418eSSumit Saxena  * mpi3mr_free_mem - Freeup adapter level data structures
53062d1d418eSSumit Saxena  * @sc: Adapter reference
53072d1d418eSSumit Saxena  *
53082d1d418eSSumit Saxena  * Return: Nothing.
53092d1d418eSSumit Saxena  */
53102d1d418eSSumit Saxena void
mpi3mr_free_mem(struct mpi3mr_softc * sc)53112d1d418eSSumit Saxena mpi3mr_free_mem(struct mpi3mr_softc *sc)
53122d1d418eSSumit Saxena {
53132d1d418eSSumit Saxena 	int i;
53142d1d418eSSumit Saxena 	struct mpi3mr_op_req_queue *op_req_q;
53152d1d418eSSumit Saxena 	struct mpi3mr_op_reply_queue *op_reply_q;
53162d1d418eSSumit Saxena 	struct mpi3mr_irq_context *irq_ctx;
53172d1d418eSSumit Saxena 
53182d1d418eSSumit Saxena 	if (sc->cmd_list) {
53192d1d418eSSumit Saxena 		for (i = 0; i < sc->max_host_ios; i++) {
53202d1d418eSSumit Saxena 			free(sc->cmd_list[i], M_MPI3MR);
53212d1d418eSSumit Saxena 		}
53222d1d418eSSumit Saxena 		free(sc->cmd_list, M_MPI3MR);
53232d1d418eSSumit Saxena 		sc->cmd_list = NULL;
53242d1d418eSSumit Saxena 	}
53252d1d418eSSumit Saxena 
53262d1d418eSSumit Saxena 	if (sc->pel_seq_number && sc->pel_seq_number_dma) {
53272d1d418eSSumit Saxena 		bus_dmamap_unload(sc->pel_seq_num_dmatag, sc->pel_seq_num_dmamap);
53282d1d418eSSumit Saxena 		bus_dmamem_free(sc->pel_seq_num_dmatag, sc->pel_seq_number, sc->pel_seq_num_dmamap);
53292d1d418eSSumit Saxena 		sc->pel_seq_number = NULL;
53302d1d418eSSumit Saxena 		if (sc->pel_seq_num_dmatag != NULL)
53312d1d418eSSumit Saxena 			bus_dma_tag_destroy(sc->pel_seq_num_dmatag);
53322d1d418eSSumit Saxena 	}
53332d1d418eSSumit Saxena 
53342d1d418eSSumit Saxena 	if (sc->throttle_groups) {
53352d1d418eSSumit Saxena 		free(sc->throttle_groups, M_MPI3MR);
53362d1d418eSSumit Saxena 		sc->throttle_groups = NULL;
53372d1d418eSSumit Saxena 	}
53382d1d418eSSumit Saxena 
53392d1d418eSSumit Saxena 	/* Free up operational queues*/
53402d1d418eSSumit Saxena 	if (sc->op_req_q) {
53412d1d418eSSumit Saxena 		for (i = 0; i < sc->num_queues; i++) {
53422d1d418eSSumit Saxena 			op_req_q = sc->op_req_q + i;
53432d1d418eSSumit Saxena 			if (op_req_q->q_base && op_req_q->q_base_phys) {
53442d1d418eSSumit Saxena 				bus_dmamap_unload(op_req_q->q_base_tag, op_req_q->q_base_dmamap);
53452d1d418eSSumit Saxena 				bus_dmamem_free(op_req_q->q_base_tag, op_req_q->q_base, op_req_q->q_base_dmamap);
53462d1d418eSSumit Saxena 				op_req_q->q_base = NULL;
53472d1d418eSSumit Saxena 				if (op_req_q->q_base_tag != NULL)
53482d1d418eSSumit Saxena 					bus_dma_tag_destroy(op_req_q->q_base_tag);
53492d1d418eSSumit Saxena 			}
53502d1d418eSSumit Saxena 		}
53512d1d418eSSumit Saxena 		free(sc->op_req_q, M_MPI3MR);
53522d1d418eSSumit Saxena 		sc->op_req_q = NULL;
53532d1d418eSSumit Saxena 	}
53542d1d418eSSumit Saxena 
53552d1d418eSSumit Saxena 	if (sc->op_reply_q) {
53562d1d418eSSumit Saxena 		for (i = 0; i < sc->num_queues; i++) {
53572d1d418eSSumit Saxena 			op_reply_q = sc->op_reply_q + i;
53582d1d418eSSumit Saxena 			if (op_reply_q->q_base && op_reply_q->q_base_phys) {
53592d1d418eSSumit Saxena 				bus_dmamap_unload(op_reply_q->q_base_tag, op_reply_q->q_base_dmamap);
53602d1d418eSSumit Saxena 				bus_dmamem_free(op_reply_q->q_base_tag, op_reply_q->q_base, op_reply_q->q_base_dmamap);
53612d1d418eSSumit Saxena 				op_reply_q->q_base = NULL;
53622d1d418eSSumit Saxena 				if (op_reply_q->q_base_tag != NULL)
53632d1d418eSSumit Saxena 					bus_dma_tag_destroy(op_reply_q->q_base_tag);
53642d1d418eSSumit Saxena 			}
53652d1d418eSSumit Saxena 		}
53662d1d418eSSumit Saxena 		free(sc->op_reply_q, M_MPI3MR);
53672d1d418eSSumit Saxena 		sc->op_reply_q = NULL;
53682d1d418eSSumit Saxena 	}
53692d1d418eSSumit Saxena 
53702d1d418eSSumit Saxena 	/* Free up chain buffers*/
53712d1d418eSSumit Saxena 	if (sc->chain_sgl_list) {
53722d1d418eSSumit Saxena 		for (i = 0; i < sc->chain_buf_count; i++) {
53732d1d418eSSumit Saxena 			if (sc->chain_sgl_list[i].buf && sc->chain_sgl_list[i].buf_phys) {
53742d1d418eSSumit Saxena 				bus_dmamap_unload(sc->chain_sgl_list_tag, sc->chain_sgl_list[i].buf_dmamap);
53752d1d418eSSumit Saxena 				bus_dmamem_free(sc->chain_sgl_list_tag, sc->chain_sgl_list[i].buf,
53762d1d418eSSumit Saxena 						sc->chain_sgl_list[i].buf_dmamap);
53772d1d418eSSumit Saxena 				sc->chain_sgl_list[i].buf = NULL;
53782d1d418eSSumit Saxena 			}
53792d1d418eSSumit Saxena 		}
53802d1d418eSSumit Saxena 		if (sc->chain_sgl_list_tag != NULL)
53812d1d418eSSumit Saxena 			bus_dma_tag_destroy(sc->chain_sgl_list_tag);
53822d1d418eSSumit Saxena 		free(sc->chain_sgl_list, M_MPI3MR);
53832d1d418eSSumit Saxena 		sc->chain_sgl_list = NULL;
53842d1d418eSSumit Saxena 	}
53852d1d418eSSumit Saxena 
53862d1d418eSSumit Saxena 	if (sc->chain_bitmap) {
53872d1d418eSSumit Saxena 		free(sc->chain_bitmap, M_MPI3MR);
53882d1d418eSSumit Saxena 		sc->chain_bitmap = NULL;
53892d1d418eSSumit Saxena 	}
53902d1d418eSSumit Saxena 
53912d1d418eSSumit Saxena 	for (i = 0; i < sc->msix_count; i++) {
53922d1d418eSSumit Saxena 		irq_ctx = sc->irq_ctx + i;
53932d1d418eSSumit Saxena 		if (irq_ctx)
53942d1d418eSSumit Saxena 			irq_ctx->op_reply_q = NULL;
53952d1d418eSSumit Saxena 	}
53962d1d418eSSumit Saxena 
53972d1d418eSSumit Saxena 	/* Free reply_buf_tag */
53982d1d418eSSumit Saxena 	if (sc->reply_buf && sc->reply_buf_phys) {
53992d1d418eSSumit Saxena 		bus_dmamap_unload(sc->reply_buf_tag, sc->reply_buf_dmamap);
54002d1d418eSSumit Saxena 		bus_dmamem_free(sc->reply_buf_tag, sc->reply_buf,
54012d1d418eSSumit Saxena 				sc->reply_buf_dmamap);
54022d1d418eSSumit Saxena 		sc->reply_buf = NULL;
54032d1d418eSSumit Saxena 		if (sc->reply_buf_tag != NULL)
54042d1d418eSSumit Saxena 			bus_dma_tag_destroy(sc->reply_buf_tag);
54052d1d418eSSumit Saxena 	}
54062d1d418eSSumit Saxena 
54072d1d418eSSumit Saxena 	/* Free reply_free_q_tag */
54082d1d418eSSumit Saxena 	if (sc->reply_free_q && sc->reply_free_q_phys) {
54092d1d418eSSumit Saxena 		bus_dmamap_unload(sc->reply_free_q_tag, sc->reply_free_q_dmamap);
54102d1d418eSSumit Saxena 		bus_dmamem_free(sc->reply_free_q_tag, sc->reply_free_q,
54112d1d418eSSumit Saxena 				sc->reply_free_q_dmamap);
54122d1d418eSSumit Saxena 		sc->reply_free_q = NULL;
54132d1d418eSSumit Saxena 		if (sc->reply_free_q_tag != NULL)
54142d1d418eSSumit Saxena 			bus_dma_tag_destroy(sc->reply_free_q_tag);
54152d1d418eSSumit Saxena 	}
54162d1d418eSSumit Saxena 
54172d1d418eSSumit Saxena 	/* Free sense_buf_tag */
54182d1d418eSSumit Saxena 	if (sc->sense_buf && sc->sense_buf_phys) {
54192d1d418eSSumit Saxena 		bus_dmamap_unload(sc->sense_buf_tag, sc->sense_buf_dmamap);
54202d1d418eSSumit Saxena 		bus_dmamem_free(sc->sense_buf_tag, sc->sense_buf,
54212d1d418eSSumit Saxena 				sc->sense_buf_dmamap);
54222d1d418eSSumit Saxena 		sc->sense_buf = NULL;
54232d1d418eSSumit Saxena 		if (sc->sense_buf_tag != NULL)
54242d1d418eSSumit Saxena 			bus_dma_tag_destroy(sc->sense_buf_tag);
54252d1d418eSSumit Saxena 	}
54262d1d418eSSumit Saxena 
54272d1d418eSSumit Saxena 	/* Free sense_buf_q_tag */
54282d1d418eSSumit Saxena 	if (sc->sense_buf_q && sc->sense_buf_q_phys) {
54292d1d418eSSumit Saxena 		bus_dmamap_unload(sc->sense_buf_q_tag, sc->sense_buf_q_dmamap);
54302d1d418eSSumit Saxena 		bus_dmamem_free(sc->sense_buf_q_tag, sc->sense_buf_q,
54312d1d418eSSumit Saxena 				sc->sense_buf_q_dmamap);
54322d1d418eSSumit Saxena 		sc->sense_buf_q = NULL;
54332d1d418eSSumit Saxena 		if (sc->sense_buf_q_tag != NULL)
54342d1d418eSSumit Saxena 			bus_dma_tag_destroy(sc->sense_buf_q_tag);
54352d1d418eSSumit Saxena 	}
54362d1d418eSSumit Saxena 
54372d1d418eSSumit Saxena 	/* Free up internal(non-IO) commands*/
54382d1d418eSSumit Saxena 	if (sc->init_cmds.reply) {
54392d1d418eSSumit Saxena 		free(sc->init_cmds.reply, M_MPI3MR);
54402d1d418eSSumit Saxena 		sc->init_cmds.reply = NULL;
54412d1d418eSSumit Saxena 	}
54422d1d418eSSumit Saxena 
54432d1d418eSSumit Saxena 	if (sc->ioctl_cmds.reply) {
54442d1d418eSSumit Saxena 		free(sc->ioctl_cmds.reply, M_MPI3MR);
54452d1d418eSSumit Saxena 		sc->ioctl_cmds.reply = NULL;
54462d1d418eSSumit Saxena 	}
54472d1d418eSSumit Saxena 
54482d1d418eSSumit Saxena 	if (sc->pel_cmds.reply) {
54492d1d418eSSumit Saxena 		free(sc->pel_cmds.reply, M_MPI3MR);
54502d1d418eSSumit Saxena 		sc->pel_cmds.reply = NULL;
54512d1d418eSSumit Saxena 	}
54522d1d418eSSumit Saxena 
54532d1d418eSSumit Saxena 	if (sc->pel_abort_cmd.reply) {
54542d1d418eSSumit Saxena 		free(sc->pel_abort_cmd.reply, M_MPI3MR);
54552d1d418eSSumit Saxena 		sc->pel_abort_cmd.reply = NULL;
54562d1d418eSSumit Saxena 	}
54572d1d418eSSumit Saxena 
54582d1d418eSSumit Saxena 	if (sc->host_tm_cmds.reply) {
54592d1d418eSSumit Saxena 		free(sc->host_tm_cmds.reply, M_MPI3MR);
54602d1d418eSSumit Saxena 		sc->host_tm_cmds.reply = NULL;
54612d1d418eSSumit Saxena 	}
54622d1d418eSSumit Saxena 
54632d1d418eSSumit Saxena 	if (sc->log_data_buffer) {
54642d1d418eSSumit Saxena 		free(sc->log_data_buffer, M_MPI3MR);
54652d1d418eSSumit Saxena 		sc->log_data_buffer = NULL;
54662d1d418eSSumit Saxena 	}
54672d1d418eSSumit Saxena 
54682d1d418eSSumit Saxena 	for (i = 0; i < MPI3MR_NUM_DEVRMCMD; i++) {
54692d1d418eSSumit Saxena 		if (sc->dev_rmhs_cmds[i].reply) {
54702d1d418eSSumit Saxena 			free(sc->dev_rmhs_cmds[i].reply, M_MPI3MR);
54712d1d418eSSumit Saxena 			sc->dev_rmhs_cmds[i].reply = NULL;
54722d1d418eSSumit Saxena 		}
54732d1d418eSSumit Saxena 	}
54742d1d418eSSumit Saxena 
54752d1d418eSSumit Saxena 	for (i = 0; i < MPI3MR_NUM_EVTACKCMD; i++) {
54762d1d418eSSumit Saxena 		if (sc->evtack_cmds[i].reply) {
54772d1d418eSSumit Saxena 			free(sc->evtack_cmds[i].reply, M_MPI3MR);
54782d1d418eSSumit Saxena 			sc->evtack_cmds[i].reply = NULL;
54792d1d418eSSumit Saxena 		}
54802d1d418eSSumit Saxena 	}
54812d1d418eSSumit Saxena 
54822d1d418eSSumit Saxena 	if (sc->removepend_bitmap) {
54832d1d418eSSumit Saxena 		free(sc->removepend_bitmap, M_MPI3MR);
54842d1d418eSSumit Saxena 		sc->removepend_bitmap = NULL;
54852d1d418eSSumit Saxena 	}
54862d1d418eSSumit Saxena 
54872d1d418eSSumit Saxena 	if (sc->devrem_bitmap) {
54882d1d418eSSumit Saxena 		free(sc->devrem_bitmap, M_MPI3MR);
54892d1d418eSSumit Saxena 		sc->devrem_bitmap = NULL;
54902d1d418eSSumit Saxena 	}
54912d1d418eSSumit Saxena 
54922d1d418eSSumit Saxena 	if (sc->evtack_cmds_bitmap) {
54932d1d418eSSumit Saxena 		free(sc->evtack_cmds_bitmap, M_MPI3MR);
54942d1d418eSSumit Saxena 		sc->evtack_cmds_bitmap = NULL;
54952d1d418eSSumit Saxena 	}
54962d1d418eSSumit Saxena 
54972d1d418eSSumit Saxena 	/* Free Admin reply*/
54982d1d418eSSumit Saxena 	if (sc->admin_reply && sc->admin_reply_phys) {
54992d1d418eSSumit Saxena 		bus_dmamap_unload(sc->admin_reply_tag, sc->admin_reply_dmamap);
55002d1d418eSSumit Saxena 		bus_dmamem_free(sc->admin_reply_tag, sc->admin_reply,
55012d1d418eSSumit Saxena 				sc->admin_reply_dmamap);
55022d1d418eSSumit Saxena 		sc->admin_reply = NULL;
55032d1d418eSSumit Saxena 		if (sc->admin_reply_tag != NULL)
55042d1d418eSSumit Saxena 			bus_dma_tag_destroy(sc->admin_reply_tag);
55052d1d418eSSumit Saxena 	}
55062d1d418eSSumit Saxena 
55072d1d418eSSumit Saxena 	/* Free Admin request*/
55082d1d418eSSumit Saxena 	if (sc->admin_req && sc->admin_req_phys) {
55092d1d418eSSumit Saxena 		bus_dmamap_unload(sc->admin_req_tag, sc->admin_req_dmamap);
55102d1d418eSSumit Saxena 		bus_dmamem_free(sc->admin_req_tag, sc->admin_req,
55112d1d418eSSumit Saxena 				sc->admin_req_dmamap);
55122d1d418eSSumit Saxena 		sc->admin_req = NULL;
55132d1d418eSSumit Saxena 		if (sc->admin_req_tag != NULL)
55142d1d418eSSumit Saxena 			bus_dma_tag_destroy(sc->admin_req_tag);
55152d1d418eSSumit Saxena 	}
55162d1d418eSSumit Saxena 	mpi3mr_free_ioctl_dma_memory(sc);
55172d1d418eSSumit Saxena 
55182d1d418eSSumit Saxena }
55192d1d418eSSumit Saxena 
55202d1d418eSSumit Saxena /**
55212d1d418eSSumit Saxena  * mpi3mr_drv_cmd_comp_reset - Flush a internal driver command
55222d1d418eSSumit Saxena  * @sc: Adapter instance reference
55232d1d418eSSumit Saxena  * @cmdptr: Internal command tracker
55242d1d418eSSumit Saxena  *
55252d1d418eSSumit Saxena  * Complete an internal driver commands with state indicating it
55262d1d418eSSumit Saxena  * is completed due to reset.
55272d1d418eSSumit Saxena  *
55282d1d418eSSumit Saxena  * Return: Nothing.
55292d1d418eSSumit Saxena  */
mpi3mr_drv_cmd_comp_reset(struct mpi3mr_softc * sc,struct mpi3mr_drvr_cmd * cmdptr)55302d1d418eSSumit Saxena static inline void mpi3mr_drv_cmd_comp_reset(struct mpi3mr_softc *sc,
55312d1d418eSSumit Saxena 	struct mpi3mr_drvr_cmd *cmdptr)
55322d1d418eSSumit Saxena {
55332d1d418eSSumit Saxena 	if (cmdptr->state & MPI3MR_CMD_PENDING) {
55342d1d418eSSumit Saxena 		cmdptr->state |= MPI3MR_CMD_RESET;
55352d1d418eSSumit Saxena 		cmdptr->state &= ~MPI3MR_CMD_PENDING;
55362d1d418eSSumit Saxena 		if (cmdptr->is_waiting) {
55372d1d418eSSumit Saxena 			complete(&cmdptr->completion);
55382d1d418eSSumit Saxena 			cmdptr->is_waiting = 0;
55392d1d418eSSumit Saxena 		} else if (cmdptr->callback)
55402d1d418eSSumit Saxena 			cmdptr->callback(sc, cmdptr);
55412d1d418eSSumit Saxena 	}
55422d1d418eSSumit Saxena }
55432d1d418eSSumit Saxena 
55442d1d418eSSumit Saxena /**
55452d1d418eSSumit Saxena  * mpi3mr_flush_drv_cmds - Flush internal driver commands
55462d1d418eSSumit Saxena  * @sc: Adapter instance reference
55472d1d418eSSumit Saxena  *
55482d1d418eSSumit Saxena  * Flush all internal driver commands post reset
55492d1d418eSSumit Saxena  *
55502d1d418eSSumit Saxena  * Return: Nothing.
55512d1d418eSSumit Saxena  */
mpi3mr_flush_drv_cmds(struct mpi3mr_softc * sc)55522d1d418eSSumit Saxena static void mpi3mr_flush_drv_cmds(struct mpi3mr_softc *sc)
55532d1d418eSSumit Saxena {
55542d1d418eSSumit Saxena 	int i = 0;
55552d1d418eSSumit Saxena 	struct mpi3mr_drvr_cmd *cmdptr;
55562d1d418eSSumit Saxena 
55572d1d418eSSumit Saxena 	cmdptr = &sc->init_cmds;
55582d1d418eSSumit Saxena 	mpi3mr_drv_cmd_comp_reset(sc, cmdptr);
55592d1d418eSSumit Saxena 
55602d1d418eSSumit Saxena 	cmdptr = &sc->ioctl_cmds;
55612d1d418eSSumit Saxena 	mpi3mr_drv_cmd_comp_reset(sc, cmdptr);
55622d1d418eSSumit Saxena 
55632d1d418eSSumit Saxena 	cmdptr = &sc->host_tm_cmds;
55642d1d418eSSumit Saxena 	mpi3mr_drv_cmd_comp_reset(sc, cmdptr);
55652d1d418eSSumit Saxena 
55662d1d418eSSumit Saxena 	for (i = 0; i < MPI3MR_NUM_DEVRMCMD; i++) {
55672d1d418eSSumit Saxena 		cmdptr = &sc->dev_rmhs_cmds[i];
55682d1d418eSSumit Saxena 		mpi3mr_drv_cmd_comp_reset(sc, cmdptr);
55692d1d418eSSumit Saxena 	}
55702d1d418eSSumit Saxena 
55712d1d418eSSumit Saxena 	for (i = 0; i < MPI3MR_NUM_EVTACKCMD; i++) {
55722d1d418eSSumit Saxena 		cmdptr = &sc->evtack_cmds[i];
55732d1d418eSSumit Saxena 		mpi3mr_drv_cmd_comp_reset(sc, cmdptr);
55742d1d418eSSumit Saxena 	}
55752d1d418eSSumit Saxena 
55762d1d418eSSumit Saxena 	cmdptr = &sc->pel_cmds;
55772d1d418eSSumit Saxena 	mpi3mr_drv_cmd_comp_reset(sc, cmdptr);
55782d1d418eSSumit Saxena 
55792d1d418eSSumit Saxena 	cmdptr = &sc->pel_abort_cmd;
55802d1d418eSSumit Saxena 	mpi3mr_drv_cmd_comp_reset(sc, cmdptr);
55812d1d418eSSumit Saxena }
55822d1d418eSSumit Saxena 
55832d1d418eSSumit Saxena 
55842d1d418eSSumit Saxena /**
55852d1d418eSSumit Saxena  * mpi3mr_memset_buffers - memset memory for a controller
55862d1d418eSSumit Saxena  * @sc: Adapter instance reference
55872d1d418eSSumit Saxena  *
55882d1d418eSSumit Saxena  * clear all the memory allocated for a controller, typically
55892d1d418eSSumit Saxena  * called post reset to reuse the memory allocated during the
55902d1d418eSSumit Saxena  * controller init.
55912d1d418eSSumit Saxena  *
55922d1d418eSSumit Saxena  * Return: Nothing.
55932d1d418eSSumit Saxena  */
mpi3mr_memset_buffers(struct mpi3mr_softc * sc)55942d1d418eSSumit Saxena static void mpi3mr_memset_buffers(struct mpi3mr_softc *sc)
55952d1d418eSSumit Saxena {
55962d1d418eSSumit Saxena 	U16 i;
55972d1d418eSSumit Saxena 	struct mpi3mr_throttle_group_info *tg;
55982d1d418eSSumit Saxena 
55992d1d418eSSumit Saxena 	memset(sc->admin_req, 0, sc->admin_req_q_sz);
56002d1d418eSSumit Saxena 	memset(sc->admin_reply, 0, sc->admin_reply_q_sz);
56012d1d418eSSumit Saxena 
56022d1d418eSSumit Saxena 	memset(sc->init_cmds.reply, 0, sc->reply_sz);
56032d1d418eSSumit Saxena 	memset(sc->ioctl_cmds.reply, 0, sc->reply_sz);
56042d1d418eSSumit Saxena 	memset(sc->host_tm_cmds.reply, 0, sc->reply_sz);
56052d1d418eSSumit Saxena 	memset(sc->pel_cmds.reply, 0, sc->reply_sz);
56062d1d418eSSumit Saxena 	memset(sc->pel_abort_cmd.reply, 0, sc->reply_sz);
56072d1d418eSSumit Saxena 	for (i = 0; i < MPI3MR_NUM_DEVRMCMD; i++)
56082d1d418eSSumit Saxena 		memset(sc->dev_rmhs_cmds[i].reply, 0, sc->reply_sz);
56092d1d418eSSumit Saxena 	for (i = 0; i < MPI3MR_NUM_EVTACKCMD; i++)
56102d1d418eSSumit Saxena 		memset(sc->evtack_cmds[i].reply, 0, sc->reply_sz);
56112d1d418eSSumit Saxena 	memset(sc->removepend_bitmap, 0, sc->dev_handle_bitmap_sz);
56122d1d418eSSumit Saxena 	memset(sc->devrem_bitmap, 0, sc->devrem_bitmap_sz);
56132d1d418eSSumit Saxena 	memset(sc->evtack_cmds_bitmap, 0, sc->evtack_cmds_bitmap_sz);
56142d1d418eSSumit Saxena 
56152d1d418eSSumit Saxena 	for (i = 0; i < sc->num_queues; i++) {
56162d1d418eSSumit Saxena 		sc->op_reply_q[i].qid = 0;
56172d1d418eSSumit Saxena 		sc->op_reply_q[i].ci = 0;
56182d1d418eSSumit Saxena 		sc->op_reply_q[i].num_replies = 0;
56192d1d418eSSumit Saxena 		sc->op_reply_q[i].ephase = 0;
56202d1d418eSSumit Saxena 		mpi3mr_atomic_set(&sc->op_reply_q[i].pend_ios, 0);
56212d1d418eSSumit Saxena 		memset(sc->op_reply_q[i].q_base, 0, sc->op_reply_q[i].qsz);
56222d1d418eSSumit Saxena 
56232d1d418eSSumit Saxena 		sc->op_req_q[i].ci = 0;
56242d1d418eSSumit Saxena 		sc->op_req_q[i].pi = 0;
56252d1d418eSSumit Saxena 		sc->op_req_q[i].num_reqs = 0;
56262d1d418eSSumit Saxena 		sc->op_req_q[i].qid = 0;
56272d1d418eSSumit Saxena 		sc->op_req_q[i].reply_qid = 0;
56282d1d418eSSumit Saxena 		memset(sc->op_req_q[i].q_base, 0, sc->op_req_q[i].qsz);
56292d1d418eSSumit Saxena 	}
56302d1d418eSSumit Saxena 
56312d1d418eSSumit Saxena 	mpi3mr_atomic_set(&sc->pend_large_data_sz, 0);
56322d1d418eSSumit Saxena 	if (sc->throttle_groups) {
56332d1d418eSSumit Saxena 		tg = sc->throttle_groups;
56342d1d418eSSumit Saxena 		for (i = 0; i < sc->num_io_throttle_group; i++, tg++) {
56352d1d418eSSumit Saxena 			tg->id = 0;
56362d1d418eSSumit Saxena 			tg->fw_qd = 0;
56372d1d418eSSumit Saxena 			tg->modified_qd = 0;
56382d1d418eSSumit Saxena 			tg->io_divert= 0;
56392d1d418eSSumit Saxena 			tg->high = 0;
56402d1d418eSSumit Saxena 			tg->low = 0;
56412d1d418eSSumit Saxena 			mpi3mr_atomic_set(&tg->pend_large_data_sz, 0);
56422d1d418eSSumit Saxena 		}
56432d1d418eSSumit Saxena  	}
56442d1d418eSSumit Saxena }
56452d1d418eSSumit Saxena 
56462d1d418eSSumit Saxena /**
56472d1d418eSSumit Saxena  * mpi3mr_invalidate_devhandles -Invalidate device handles
56482d1d418eSSumit Saxena  * @sc: Adapter instance reference
56492d1d418eSSumit Saxena  *
56502d1d418eSSumit Saxena  * Invalidate the device handles in the target device structures
56512d1d418eSSumit Saxena  * . Called post reset prior to reinitializing the controller.
56522d1d418eSSumit Saxena  *
56532d1d418eSSumit Saxena  * Return: Nothing.
56542d1d418eSSumit Saxena  */
mpi3mr_invalidate_devhandles(struct mpi3mr_softc * sc)56552d1d418eSSumit Saxena static void mpi3mr_invalidate_devhandles(struct mpi3mr_softc *sc)
56562d1d418eSSumit Saxena {
56572d1d418eSSumit Saxena 	struct mpi3mr_target *target = NULL;
56582d1d418eSSumit Saxena 
56592d1d418eSSumit Saxena 	mtx_lock_spin(&sc->target_lock);
56602d1d418eSSumit Saxena 	TAILQ_FOREACH(target, &sc->cam_sc->tgt_list, tgt_next) {
56612d1d418eSSumit Saxena 		if (target) {
56622d1d418eSSumit Saxena 			target->dev_handle = MPI3MR_INVALID_DEV_HANDLE;
56632d1d418eSSumit Saxena 			target->io_throttle_enabled = 0;
56642d1d418eSSumit Saxena 			target->io_divert = 0;
56652d1d418eSSumit Saxena 			target->throttle_group = NULL;
5666*3f3a1554SChandrakanth patil 			target->ws_len = 0;
56672d1d418eSSumit Saxena 		}
56682d1d418eSSumit Saxena 	}
56692d1d418eSSumit Saxena 	mtx_unlock_spin(&sc->target_lock);
56702d1d418eSSumit Saxena }
56712d1d418eSSumit Saxena 
56722d1d418eSSumit Saxena /**
56732d1d418eSSumit Saxena  * mpi3mr_rfresh_tgtdevs - Refresh target device exposure
56742d1d418eSSumit Saxena  * @sc: Adapter instance reference
56752d1d418eSSumit Saxena  *
56762d1d418eSSumit Saxena  * This is executed post controller reset to identify any
56772d1d418eSSumit Saxena  * missing devices during reset and remove from the upper layers
56782d1d418eSSumit Saxena  * or expose any newly detected device to the upper layers.
56792d1d418eSSumit Saxena  *
56802d1d418eSSumit Saxena  * Return: Nothing.
56812d1d418eSSumit Saxena  */
56822d1d418eSSumit Saxena 
mpi3mr_rfresh_tgtdevs(struct mpi3mr_softc * sc)56832d1d418eSSumit Saxena static void mpi3mr_rfresh_tgtdevs(struct mpi3mr_softc *sc)
56842d1d418eSSumit Saxena {
56852d1d418eSSumit Saxena 	struct mpi3mr_target *target = NULL;
56862d1d418eSSumit Saxena 	struct mpi3mr_target *target_temp = NULL;
56872d1d418eSSumit Saxena 
56882d1d418eSSumit Saxena 	TAILQ_FOREACH_SAFE(target, &sc->cam_sc->tgt_list, tgt_next, target_temp) {
56892d1d418eSSumit Saxena 		if (target->dev_handle == MPI3MR_INVALID_DEV_HANDLE) {
56902d1d418eSSumit Saxena 			if (target->exposed_to_os)
56912d1d418eSSumit Saxena 				mpi3mr_remove_device_from_os(sc, target->dev_handle);
56922d1d418eSSumit Saxena 			mpi3mr_remove_device_from_list(sc, target, true);
56930d705645SChandrakanth patil 		} else if (target->is_hidden && target->exposed_to_os) {
56940d705645SChandrakanth patil 				mpi3mr_remove_device_from_os(sc, target->dev_handle);
56952d1d418eSSumit Saxena 		}
56962d1d418eSSumit Saxena 	}
56972d1d418eSSumit Saxena 
56982d1d418eSSumit Saxena 	TAILQ_FOREACH(target, &sc->cam_sc->tgt_list, tgt_next) {
56992d1d418eSSumit Saxena 		if ((target->dev_handle != MPI3MR_INVALID_DEV_HANDLE) &&
57002d1d418eSSumit Saxena 		    !target->is_hidden && !target->exposed_to_os) {
57012d1d418eSSumit Saxena 			mpi3mr_add_device(sc, target->per_id);
57022d1d418eSSumit Saxena 		}
57032d1d418eSSumit Saxena 	}
57042d1d418eSSumit Saxena 
57052d1d418eSSumit Saxena }
57062d1d418eSSumit Saxena 
mpi3mr_flush_io(struct mpi3mr_softc * sc)57072d1d418eSSumit Saxena static void mpi3mr_flush_io(struct mpi3mr_softc *sc)
57082d1d418eSSumit Saxena {
57092d1d418eSSumit Saxena 	int i;
57102d1d418eSSumit Saxena 	struct mpi3mr_cmd *cmd = NULL;
57112d1d418eSSumit Saxena 	union ccb *ccb = NULL;
57122d1d418eSSumit Saxena 
57132d1d418eSSumit Saxena 	for (i = 0; i < sc->max_host_ios; i++) {
57142d1d418eSSumit Saxena 		cmd = sc->cmd_list[i];
57152d1d418eSSumit Saxena 
57162d1d418eSSumit Saxena 		if (cmd && cmd->ccb) {
57172d1d418eSSumit Saxena 			if (cmd->callout_owner) {
57182d1d418eSSumit Saxena 				ccb = (union ccb *)(cmd->ccb);
57192d1d418eSSumit Saxena 				ccb->ccb_h.status = CAM_SCSI_BUS_RESET;
5720571f1d06SChandrakanth patil 				mpi3mr_atomic_dec(&sc->fw_outstanding);
5721571f1d06SChandrakanth patil 				mpi3mr_atomic_dec(&cmd->targ->outstanding);
57222d1d418eSSumit Saxena 				mpi3mr_cmd_done(sc, cmd);
57232d1d418eSSumit Saxena 			} else {
57242d1d418eSSumit Saxena 				cmd->ccb = NULL;
57252d1d418eSSumit Saxena 				mpi3mr_release_command(cmd);
57262d1d418eSSumit Saxena 			}
57272d1d418eSSumit Saxena 		}
57282d1d418eSSumit Saxena 	}
57292d1d418eSSumit Saxena }
57302d1d418eSSumit Saxena /**
57312d1d418eSSumit Saxena  * mpi3mr_clear_reset_history - Clear reset history
57322d1d418eSSumit Saxena  * @sc: Adapter instance reference
57332d1d418eSSumit Saxena  *
57342d1d418eSSumit Saxena  * Write the reset history bit in IOC Status to clear the bit,
57352d1d418eSSumit Saxena  * if it is already set.
57362d1d418eSSumit Saxena  *
57372d1d418eSSumit Saxena  * Return: Nothing.
57382d1d418eSSumit Saxena  */
mpi3mr_clear_reset_history(struct mpi3mr_softc * sc)57392d1d418eSSumit Saxena static inline void mpi3mr_clear_reset_history(struct mpi3mr_softc *sc)
57402d1d418eSSumit Saxena {
57412d1d418eSSumit Saxena 	U32 ioc_status;
57422d1d418eSSumit Saxena 
57432d1d418eSSumit Saxena 	ioc_status = mpi3mr_regread(sc, MPI3_SYSIF_IOC_STATUS_OFFSET);
57442d1d418eSSumit Saxena 	if (ioc_status & MPI3_SYSIF_IOC_STATUS_RESET_HISTORY)
57452d1d418eSSumit Saxena 		mpi3mr_regwrite(sc, MPI3_SYSIF_IOC_STATUS_OFFSET, ioc_status);
57462d1d418eSSumit Saxena }
57472d1d418eSSumit Saxena 
57482d1d418eSSumit Saxena /**
57492d1d418eSSumit Saxena  * mpi3mr_set_diagsave - Set diag save bit for snapdump
57502d1d418eSSumit Saxena  * @sc: Adapter reference
57512d1d418eSSumit Saxena  *
57522d1d418eSSumit Saxena  * Set diag save bit in IOC configuration register to enable
57532d1d418eSSumit Saxena  * snapdump.
57542d1d418eSSumit Saxena  *
57552d1d418eSSumit Saxena  * Return: Nothing.
57562d1d418eSSumit Saxena  */
mpi3mr_set_diagsave(struct mpi3mr_softc * sc)57572d1d418eSSumit Saxena static inline void mpi3mr_set_diagsave(struct mpi3mr_softc *sc)
57582d1d418eSSumit Saxena {
57592d1d418eSSumit Saxena 	U32 ioc_config;
57602d1d418eSSumit Saxena 
57612d1d418eSSumit Saxena 	ioc_config =
57622d1d418eSSumit Saxena 	    mpi3mr_regread(sc, MPI3_SYSIF_IOC_CONFIG_OFFSET);
57632d1d418eSSumit Saxena 	ioc_config |= MPI3_SYSIF_IOC_CONFIG_DIAG_SAVE;
57642d1d418eSSumit Saxena 	mpi3mr_regwrite(sc, MPI3_SYSIF_IOC_CONFIG_OFFSET, ioc_config);
57652d1d418eSSumit Saxena }
57662d1d418eSSumit Saxena 
57672d1d418eSSumit Saxena /**
57682d1d418eSSumit Saxena  * mpi3mr_issue_reset - Issue reset to the controller
57692d1d418eSSumit Saxena  * @sc: Adapter reference
57702d1d418eSSumit Saxena  * @reset_type: Reset type
57712d1d418eSSumit Saxena  * @reset_reason: Reset reason code
57722d1d418eSSumit Saxena  *
57732d1d418eSSumit Saxena  * Unlock the host diagnostic registers and write the specific
57742d1d418eSSumit Saxena  * reset type to that, wait for reset acknowledgement from the
57752d1d418eSSumit Saxena  * controller, if the reset is not successful retry for the
57762d1d418eSSumit Saxena  * predefined number of times.
57772d1d418eSSumit Saxena  *
57782d1d418eSSumit Saxena  * Return: 0 on success, non-zero on failure.
57792d1d418eSSumit Saxena  */
mpi3mr_issue_reset(struct mpi3mr_softc * sc,U16 reset_type,U16 reset_reason)57802d1d418eSSumit Saxena static int mpi3mr_issue_reset(struct mpi3mr_softc *sc, U16 reset_type,
57813012fa8fSChandrakanth patil 	U16 reset_reason)
57822d1d418eSSumit Saxena {
57832d1d418eSSumit Saxena 	int retval = -1;
57842d1d418eSSumit Saxena 	U8 unlock_retry_count = 0;
57853012fa8fSChandrakanth patil 	U32 host_diagnostic, ioc_status, ioc_config, scratch_pad0;
57862d1d418eSSumit Saxena 	U32 timeout = MPI3MR_RESET_ACK_TIMEOUT * 10;
57872d1d418eSSumit Saxena 
57882d1d418eSSumit Saxena 	if ((reset_type != MPI3_SYSIF_HOST_DIAG_RESET_ACTION_SOFT_RESET) &&
57892d1d418eSSumit Saxena 	    (reset_type != MPI3_SYSIF_HOST_DIAG_RESET_ACTION_DIAG_FAULT))
57902d1d418eSSumit Saxena 		return retval;
57912d1d418eSSumit Saxena 	if (sc->unrecoverable)
57922d1d418eSSumit Saxena 		return retval;
57932d1d418eSSumit Saxena 
57942d1d418eSSumit Saxena 	if (reset_reason == MPI3MR_RESET_FROM_FIRMWARE) {
57952d1d418eSSumit Saxena 		retval = 0;
57962d1d418eSSumit Saxena 		return retval;
57972d1d418eSSumit Saxena 	}
57982d1d418eSSumit Saxena 
57992d1d418eSSumit Saxena 	mpi3mr_dprint(sc, MPI3MR_INFO, "%s reset due to %s(0x%x)\n",
58002d1d418eSSumit Saxena 	    mpi3mr_reset_type_name(reset_type),
58012d1d418eSSumit Saxena 	    mpi3mr_reset_rc_name(reset_reason), reset_reason);
58022d1d418eSSumit Saxena 
58032d1d418eSSumit Saxena 	mpi3mr_clear_reset_history(sc);
58042d1d418eSSumit Saxena 	do {
58052d1d418eSSumit Saxena 		mpi3mr_dprint(sc, MPI3MR_INFO,
58062d1d418eSSumit Saxena 		    "Write magic sequence to unlock host diag register (retry=%d)\n",
58072d1d418eSSumit Saxena 		    ++unlock_retry_count);
58082d1d418eSSumit Saxena 		if (unlock_retry_count >= MPI3MR_HOSTDIAG_UNLOCK_RETRY_COUNT) {
58092d1d418eSSumit Saxena 			mpi3mr_dprint(sc, MPI3MR_ERROR,
58102d1d418eSSumit Saxena 			    "%s reset failed! due to host diag register unlock failure"
58112d1d418eSSumit Saxena 			    "host_diagnostic(0x%08x)\n", mpi3mr_reset_type_name(reset_type),
58122d1d418eSSumit Saxena 			    host_diagnostic);
58132d1d418eSSumit Saxena 			sc->unrecoverable = 1;
58142d1d418eSSumit Saxena 			return retval;
58152d1d418eSSumit Saxena 		}
58162d1d418eSSumit Saxena 
58172d1d418eSSumit Saxena 		mpi3mr_regwrite(sc, MPI3_SYSIF_WRITE_SEQUENCE_OFFSET,
58182d1d418eSSumit Saxena 			MPI3_SYSIF_WRITE_SEQUENCE_KEY_VALUE_FLUSH);
58192d1d418eSSumit Saxena 		mpi3mr_regwrite(sc, MPI3_SYSIF_WRITE_SEQUENCE_OFFSET,
58202d1d418eSSumit Saxena 			MPI3_SYSIF_WRITE_SEQUENCE_KEY_VALUE_1ST);
58212d1d418eSSumit Saxena 		mpi3mr_regwrite(sc, MPI3_SYSIF_WRITE_SEQUENCE_OFFSET,
58222d1d418eSSumit Saxena 			MPI3_SYSIF_WRITE_SEQUENCE_KEY_VALUE_2ND);
58232d1d418eSSumit Saxena 		mpi3mr_regwrite(sc, MPI3_SYSIF_WRITE_SEQUENCE_OFFSET,
58242d1d418eSSumit Saxena 			MPI3_SYSIF_WRITE_SEQUENCE_KEY_VALUE_3RD);
58252d1d418eSSumit Saxena 		mpi3mr_regwrite(sc, MPI3_SYSIF_WRITE_SEQUENCE_OFFSET,
58262d1d418eSSumit Saxena 			MPI3_SYSIF_WRITE_SEQUENCE_KEY_VALUE_4TH);
58272d1d418eSSumit Saxena 		mpi3mr_regwrite(sc, MPI3_SYSIF_WRITE_SEQUENCE_OFFSET,
58282d1d418eSSumit Saxena 			MPI3_SYSIF_WRITE_SEQUENCE_KEY_VALUE_5TH);
58292d1d418eSSumit Saxena 		mpi3mr_regwrite(sc, MPI3_SYSIF_WRITE_SEQUENCE_OFFSET,
58302d1d418eSSumit Saxena 			MPI3_SYSIF_WRITE_SEQUENCE_KEY_VALUE_6TH);
58312d1d418eSSumit Saxena 
58322d1d418eSSumit Saxena 		DELAY(1000); /* delay in usec */
58332d1d418eSSumit Saxena 		host_diagnostic = mpi3mr_regread(sc, MPI3_SYSIF_HOST_DIAG_OFFSET);
58342d1d418eSSumit Saxena 		mpi3mr_dprint(sc, MPI3MR_INFO,
58352d1d418eSSumit Saxena 		    "wrote magic sequence: retry_count(%d), host_diagnostic(0x%08x)\n",
58362d1d418eSSumit Saxena 		    unlock_retry_count, host_diagnostic);
58372d1d418eSSumit Saxena 	} while (!(host_diagnostic & MPI3_SYSIF_HOST_DIAG_DIAG_WRITE_ENABLE));
58382d1d418eSSumit Saxena 
58393012fa8fSChandrakanth patil 	scratch_pad0 = ((MPI3MR_RESET_REASON_OSTYPE_FREEBSD <<
58403012fa8fSChandrakanth patil 			MPI3MR_RESET_REASON_OSTYPE_SHIFT) |
58413012fa8fSChandrakanth patil 			(sc->facts.ioc_num <<
58423012fa8fSChandrakanth patil 			MPI3MR_RESET_REASON_IOCNUM_SHIFT) | reset_reason);
58433012fa8fSChandrakanth patil 	mpi3mr_regwrite(sc, MPI3_SYSIF_SCRATCHPAD0_OFFSET, scratch_pad0);
58442d1d418eSSumit Saxena 	mpi3mr_regwrite(sc, MPI3_SYSIF_HOST_DIAG_OFFSET, host_diagnostic | reset_type);
58452d1d418eSSumit Saxena 
58462d1d418eSSumit Saxena 	if (reset_type == MPI3_SYSIF_HOST_DIAG_RESET_ACTION_SOFT_RESET) {
58472d1d418eSSumit Saxena 		do {
58482d1d418eSSumit Saxena 			ioc_status = mpi3mr_regread(sc, MPI3_SYSIF_IOC_STATUS_OFFSET);
58492d1d418eSSumit Saxena 			if (ioc_status &
58502d1d418eSSumit Saxena 			    MPI3_SYSIF_IOC_STATUS_RESET_HISTORY) {
58512d1d418eSSumit Saxena 				ioc_config =
58522d1d418eSSumit Saxena 				    mpi3mr_regread(sc, MPI3_SYSIF_IOC_CONFIG_OFFSET);
58532d1d418eSSumit Saxena 				if (mpi3mr_soft_reset_success(ioc_status,
58542d1d418eSSumit Saxena 				    ioc_config)) {
58552d1d418eSSumit Saxena 					mpi3mr_clear_reset_history(sc);
58562d1d418eSSumit Saxena 					retval = 0;
58572d1d418eSSumit Saxena 					break;
58582d1d418eSSumit Saxena 				}
58592d1d418eSSumit Saxena 			}
58602d1d418eSSumit Saxena 			DELAY(100 * 1000);
58612d1d418eSSumit Saxena 		} while (--timeout);
58622d1d418eSSumit Saxena 	} else if (reset_type == MPI3_SYSIF_HOST_DIAG_RESET_ACTION_DIAG_FAULT) {
58632d1d418eSSumit Saxena 		do {
58642d1d418eSSumit Saxena 			ioc_status = mpi3mr_regread(sc, MPI3_SYSIF_IOC_STATUS_OFFSET);
58652d1d418eSSumit Saxena 			if (mpi3mr_diagfault_success(sc, ioc_status)) {
58662d1d418eSSumit Saxena 				retval = 0;
58672d1d418eSSumit Saxena 				break;
58682d1d418eSSumit Saxena 			}
58692d1d418eSSumit Saxena 			DELAY(100 * 1000);
58702d1d418eSSumit Saxena 		} while (--timeout);
58712d1d418eSSumit Saxena 	}
58722d1d418eSSumit Saxena 
58732d1d418eSSumit Saxena 	mpi3mr_regwrite(sc, MPI3_SYSIF_WRITE_SEQUENCE_OFFSET,
58742d1d418eSSumit Saxena 		MPI3_SYSIF_WRITE_SEQUENCE_KEY_VALUE_2ND);
58752d1d418eSSumit Saxena 
58762d1d418eSSumit Saxena 	ioc_status = mpi3mr_regread(sc, MPI3_SYSIF_IOC_STATUS_OFFSET);
58772d1d418eSSumit Saxena 	ioc_config = mpi3mr_regread(sc, MPI3_SYSIF_IOC_CONFIG_OFFSET);
58782d1d418eSSumit Saxena 
58792d1d418eSSumit Saxena 	mpi3mr_dprint(sc, MPI3MR_INFO,
58802d1d418eSSumit Saxena 	    "IOC Status/Config after %s reset is (0x%x)/(0x%x)\n",
58812d1d418eSSumit Saxena 	    !retval ? "successful":"failed", ioc_status,
58822d1d418eSSumit Saxena 	    ioc_config);
58832d1d418eSSumit Saxena 
58842d1d418eSSumit Saxena 	if (retval)
58852d1d418eSSumit Saxena 		sc->unrecoverable = 1;
58862d1d418eSSumit Saxena 
58872d1d418eSSumit Saxena 	return retval;
58882d1d418eSSumit Saxena }
58892d1d418eSSumit Saxena 
mpi3mr_cleanup_event_taskq(struct mpi3mr_softc * sc)58902d1d418eSSumit Saxena inline void mpi3mr_cleanup_event_taskq(struct mpi3mr_softc *sc)
58912d1d418eSSumit Saxena {
5892b411372bSWarner Losh 	/*
5893b411372bSWarner Losh 	 * Block the taskqueue before draining.  This means any new tasks won't
5894272a4060SWarner Losh 	 * be queued to the taskqueue worker thread.  But it doesn't stop the
5895272a4060SWarner Losh 	 * current workers that are running.  taskqueue_drain waits for those
5896272a4060SWarner Losh 	 * correctly in the case of thread backed taskqueues.  The while loop
5897272a4060SWarner Losh 	 * ensures that all taskqueue threads have finished their current tasks.
5898b411372bSWarner Losh 	 */
58992d1d418eSSumit Saxena 	taskqueue_block(sc->cam_sc->ev_tq);
5900272a4060SWarner Losh 	while (taskqueue_cancel(sc->cam_sc->ev_tq, &sc->cam_sc->ev_task, NULL) != 0) {
5901b411372bSWarner Losh 		taskqueue_drain(sc->cam_sc->ev_tq, &sc->cam_sc->ev_task);
59022d1d418eSSumit Saxena 	}
5903272a4060SWarner Losh }
59042d1d418eSSumit Saxena 
59052d1d418eSSumit Saxena /**
59062d1d418eSSumit Saxena  * mpi3mr_soft_reset_handler - Reset the controller
59072d1d418eSSumit Saxena  * @sc: Adapter instance reference
59082d1d418eSSumit Saxena  * @reset_reason: Reset reason code
59092d1d418eSSumit Saxena  * @snapdump: snapdump enable/disbale bit
59102d1d418eSSumit Saxena  *
59112d1d418eSSumit Saxena  * This is an handler for recovering controller by issuing soft
59122d1d418eSSumit Saxena  * reset or diag fault reset. This is a blocking function and
59132d1d418eSSumit Saxena  * when one reset is executed if any other resets they will be
59142d1d418eSSumit Saxena  * blocked. All IOCTLs/IO will be blocked during the reset. If
59152d1d418eSSumit Saxena  * controller reset is successful then the controller will be
59162d1d418eSSumit Saxena  * reinitalized, otherwise the controller will be marked as not
59172d1d418eSSumit Saxena  * recoverable
59182d1d418eSSumit Saxena  *
59192d1d418eSSumit Saxena  * Return: 0 on success, non-zero on failure.
59202d1d418eSSumit Saxena  */
mpi3mr_soft_reset_handler(struct mpi3mr_softc * sc,U16 reset_reason,bool snapdump)59212d1d418eSSumit Saxena int mpi3mr_soft_reset_handler(struct mpi3mr_softc *sc,
59223012fa8fSChandrakanth patil 	U16 reset_reason, bool snapdump)
59232d1d418eSSumit Saxena {
59242d1d418eSSumit Saxena 	int retval = 0, i = 0;
59252d1d418eSSumit Saxena 	enum mpi3mr_iocstate ioc_state;
59262d1d418eSSumit Saxena 
59272d1d418eSSumit Saxena 	mpi3mr_dprint(sc, MPI3MR_INFO, "soft reset invoked: reason code: %s\n",
59282d1d418eSSumit Saxena 	    mpi3mr_reset_rc_name(reset_reason));
59292d1d418eSSumit Saxena 
59302d1d418eSSumit Saxena 	if ((reset_reason == MPI3MR_RESET_FROM_IOCTL) &&
59312d1d418eSSumit Saxena 	     (sc->reset.ioctl_reset_snapdump != true))
59322d1d418eSSumit Saxena 		snapdump = false;
59332d1d418eSSumit Saxena 
59342d1d418eSSumit Saxena 	mpi3mr_dprint(sc, MPI3MR_INFO,
59352d1d418eSSumit Saxena 	    "soft_reset_handler: wait if diag save is in progress\n");
59362d1d418eSSumit Saxena 	while (sc->diagsave_timeout)
59372d1d418eSSumit Saxena 		DELAY(1000 * 1000);
59382d1d418eSSumit Saxena 
59392d1d418eSSumit Saxena 	ioc_state = mpi3mr_get_iocstate(sc);
59402d1d418eSSumit Saxena 	if (ioc_state == MRIOC_STATE_UNRECOVERABLE) {
59412d1d418eSSumit Saxena 		mpi3mr_dprint(sc, MPI3MR_ERROR, "controller is in unrecoverable state, exit\n");
59422d1d418eSSumit Saxena 		sc->reset.type = MPI3MR_NO_RESET;
59432d1d418eSSumit Saxena 		sc->reset.reason = MPI3MR_DEFAULT_RESET_REASON;
59442d1d418eSSumit Saxena 		sc->reset.status = -1;
59452d1d418eSSumit Saxena 		sc->reset.ioctl_reset_snapdump = false;
59462d1d418eSSumit Saxena 		return -1;
59472d1d418eSSumit Saxena 	}
59482d1d418eSSumit Saxena 
59492d1d418eSSumit Saxena 	if (sc->reset_in_progress) {
59502d1d418eSSumit Saxena 		mpi3mr_dprint(sc, MPI3MR_INFO, "reset is already in progress, exit\n");
59512d1d418eSSumit Saxena 		return -1;
59522d1d418eSSumit Saxena 	}
59532d1d418eSSumit Saxena 
59542d1d418eSSumit Saxena 	/* Pause IOs, drain and block the event taskqueue */
59552d1d418eSSumit Saxena 	xpt_freeze_simq(sc->cam_sc->sim, 1);
59562d1d418eSSumit Saxena 
59572d1d418eSSumit Saxena 	mpi3mr_cleanup_event_taskq(sc);
59582d1d418eSSumit Saxena 
59592d1d418eSSumit Saxena 	sc->reset_in_progress = 1;
59602d1d418eSSumit Saxena 	sc->block_ioctls = 1;
59612d1d418eSSumit Saxena 
59622d1d418eSSumit Saxena 	while (mpi3mr_atomic_read(&sc->pend_ioctls) && (i < PEND_IOCTLS_COMP_WAIT_TIME)) {
59632d1d418eSSumit Saxena 		ioc_state = mpi3mr_get_iocstate(sc);
59642d1d418eSSumit Saxena 		if (ioc_state == MRIOC_STATE_FAULT)
59652d1d418eSSumit Saxena 			break;
59662d1d418eSSumit Saxena 		i++;
59672d1d418eSSumit Saxena 		if (!(i % 5)) {
59682d1d418eSSumit Saxena 			mpi3mr_dprint(sc, MPI3MR_INFO,
59692d1d418eSSumit Saxena 			    "[%2ds]waiting for IOCTL to be finished from %s\n", i, __func__);
59702d1d418eSSumit Saxena 		}
59712d1d418eSSumit Saxena 		DELAY(1000 * 1000);
59722d1d418eSSumit Saxena 	}
59732d1d418eSSumit Saxena 
59742d1d418eSSumit Saxena 	if ((!snapdump) && (reset_reason != MPI3MR_RESET_FROM_FAULT_WATCH) &&
59752d1d418eSSumit Saxena 	    (reset_reason != MPI3MR_RESET_FROM_FIRMWARE) &&
59762d1d418eSSumit Saxena 	    (reset_reason != MPI3MR_RESET_FROM_CIACTIV_FAULT)) {
59772d1d418eSSumit Saxena 
59782d1d418eSSumit Saxena 		mpi3mr_dprint(sc, MPI3MR_INFO, "Turn off events prior to reset\n");
59792d1d418eSSumit Saxena 
59802d1d418eSSumit Saxena 		for (i = 0; i < MPI3_EVENT_NOTIFY_EVENTMASK_WORDS; i++)
59812d1d418eSSumit Saxena 			sc->event_masks[i] = -1;
59822d1d418eSSumit Saxena 		mpi3mr_issue_event_notification(sc);
59832d1d418eSSumit Saxena 	}
59842d1d418eSSumit Saxena 
59852d1d418eSSumit Saxena 	mpi3mr_disable_interrupts(sc);
59862d1d418eSSumit Saxena 
59872d1d418eSSumit Saxena 	if (snapdump)
59882d1d418eSSumit Saxena 		mpi3mr_trigger_snapdump(sc, reset_reason);
59892d1d418eSSumit Saxena 
59902d1d418eSSumit Saxena 	retval = mpi3mr_issue_reset(sc,
59912d1d418eSSumit Saxena 	    MPI3_SYSIF_HOST_DIAG_RESET_ACTION_SOFT_RESET, reset_reason);
59922d1d418eSSumit Saxena 	if (retval) {
59932d1d418eSSumit Saxena 		mpi3mr_dprint(sc, MPI3MR_ERROR, "Failed to issue soft reset to the ioc\n");
59942d1d418eSSumit Saxena 		goto out;
59952d1d418eSSumit Saxena 	}
59962d1d418eSSumit Saxena 
59972d1d418eSSumit Saxena 	mpi3mr_flush_drv_cmds(sc);
59982d1d418eSSumit Saxena 	mpi3mr_flush_io(sc);
59992d1d418eSSumit Saxena 	mpi3mr_invalidate_devhandles(sc);
60002d1d418eSSumit Saxena 	mpi3mr_memset_buffers(sc);
60012d1d418eSSumit Saxena 
60022d1d418eSSumit Saxena 	if (sc->prepare_for_reset) {
60032d1d418eSSumit Saxena 		sc->prepare_for_reset = 0;
60042d1d418eSSumit Saxena 		sc->prepare_for_reset_timeout_counter = 0;
60052d1d418eSSumit Saxena 	}
60062d1d418eSSumit Saxena 
60072d1d418eSSumit Saxena 	retval = mpi3mr_initialize_ioc(sc, MPI3MR_INIT_TYPE_RESET);
60082d1d418eSSumit Saxena 	if (retval) {
60092d1d418eSSumit Saxena 		mpi3mr_dprint(sc, MPI3MR_ERROR, "reinit after soft reset failed: reason %d\n",
60102d1d418eSSumit Saxena 		    reset_reason);
60112d1d418eSSumit Saxena 		goto out;
60122d1d418eSSumit Saxena 	}
60132d1d418eSSumit Saxena 
60142d1d418eSSumit Saxena 	DELAY((1000 * 1000) * 10);
60152d1d418eSSumit Saxena out:
60162d1d418eSSumit Saxena 	if (!retval) {
60172d1d418eSSumit Saxena 		sc->diagsave_timeout = 0;
60182d1d418eSSumit Saxena 		sc->reset_in_progress = 0;
60192d1d418eSSumit Saxena 		mpi3mr_rfresh_tgtdevs(sc);
60202d1d418eSSumit Saxena 		sc->ts_update_counter = 0;
60212d1d418eSSumit Saxena 		sc->block_ioctls = 0;
60222d1d418eSSumit Saxena 		sc->pel_abort_requested = 0;
60232d1d418eSSumit Saxena 		if (sc->pel_wait_pend) {
60242d1d418eSSumit Saxena 			sc->pel_cmds.retry_count = 0;
60252d1d418eSSumit Saxena 			mpi3mr_issue_pel_wait(sc, &sc->pel_cmds);
60262d1d418eSSumit Saxena 			mpi3mr_app_send_aen(sc);
60272d1d418eSSumit Saxena 		}
60282d1d418eSSumit Saxena 	} else {
60292d1d418eSSumit Saxena 		mpi3mr_issue_reset(sc,
60302d1d418eSSumit Saxena 		    MPI3_SYSIF_HOST_DIAG_RESET_ACTION_DIAG_FAULT, reset_reason);
60312d1d418eSSumit Saxena 		sc->unrecoverable = 1;
60322d1d418eSSumit Saxena 		sc->reset_in_progress = 0;
60332d1d418eSSumit Saxena 	}
60342d1d418eSSumit Saxena 
60352d1d418eSSumit Saxena 	mpi3mr_dprint(sc, MPI3MR_INFO, "Soft Reset: %s\n", ((retval == 0) ? "SUCCESS" : "FAILED"));
60362d1d418eSSumit Saxena 
60372d1d418eSSumit Saxena 	taskqueue_unblock(sc->cam_sc->ev_tq);
60382d1d418eSSumit Saxena 	xpt_release_simq(sc->cam_sc->sim, 1);
60392d1d418eSSumit Saxena 
60402d1d418eSSumit Saxena 	sc->reset.type = MPI3MR_NO_RESET;
60412d1d418eSSumit Saxena 	sc->reset.reason = MPI3MR_DEFAULT_RESET_REASON;
60422d1d418eSSumit Saxena 	sc->reset.status = retval;
60432d1d418eSSumit Saxena 	sc->reset.ioctl_reset_snapdump = false;
60442d1d418eSSumit Saxena 
60452d1d418eSSumit Saxena 	return retval;
60462d1d418eSSumit Saxena }
60472d1d418eSSumit Saxena 
60482d1d418eSSumit Saxena /**
60492d1d418eSSumit Saxena  * mpi3mr_issue_ioc_shutdown - shutdown controller
60502d1d418eSSumit Saxena  * @sc: Adapter instance reference
60512d1d418eSSumit Saxena  *
60522d1d418eSSumit Saxena  * Send shutodwn notification to the controller and wait for the
60532d1d418eSSumit Saxena  * shutdown_timeout for it to be completed.
60542d1d418eSSumit Saxena  *
60552d1d418eSSumit Saxena  * Return: Nothing.
60562d1d418eSSumit Saxena  */
mpi3mr_issue_ioc_shutdown(struct mpi3mr_softc * sc)60572d1d418eSSumit Saxena static void mpi3mr_issue_ioc_shutdown(struct mpi3mr_softc *sc)
60582d1d418eSSumit Saxena {
60592d1d418eSSumit Saxena 	U32 ioc_config, ioc_status;
60602d1d418eSSumit Saxena 	U8 retval = 1, retry = 0;
60612d1d418eSSumit Saxena 	U32 timeout = MPI3MR_DEFAULT_SHUTDOWN_TIME * 10;
60622d1d418eSSumit Saxena 
60632d1d418eSSumit Saxena 	mpi3mr_dprint(sc, MPI3MR_INFO, "sending shutdown notification\n");
60642d1d418eSSumit Saxena 	if (sc->unrecoverable) {
60652d1d418eSSumit Saxena 		mpi3mr_dprint(sc, MPI3MR_ERROR,
60662d1d418eSSumit Saxena 		    "controller is unrecoverable, shutdown not issued\n");
60672d1d418eSSumit Saxena 		return;
60682d1d418eSSumit Saxena 	}
60692d1d418eSSumit Saxena 	ioc_status = mpi3mr_regread(sc, MPI3_SYSIF_IOC_STATUS_OFFSET);
60702d1d418eSSumit Saxena 	if ((ioc_status & MPI3_SYSIF_IOC_STATUS_SHUTDOWN_MASK)
60712d1d418eSSumit Saxena 	    == MPI3_SYSIF_IOC_STATUS_SHUTDOWN_IN_PROGRESS) {
60722d1d418eSSumit Saxena 		mpi3mr_dprint(sc, MPI3MR_ERROR, "shutdown already in progress\n");
60732d1d418eSSumit Saxena 		return;
60742d1d418eSSumit Saxena 	}
60752d1d418eSSumit Saxena 
60762d1d418eSSumit Saxena 	ioc_config = mpi3mr_regread(sc, MPI3_SYSIF_IOC_CONFIG_OFFSET);
60772d1d418eSSumit Saxena 	ioc_config |= MPI3_SYSIF_IOC_CONFIG_SHUTDOWN_NORMAL;
60782d1d418eSSumit Saxena 	ioc_config |= MPI3_SYSIF_IOC_CONFIG_DEVICE_SHUTDOWN_SEND_REQ;
60792d1d418eSSumit Saxena 
60802d1d418eSSumit Saxena 	mpi3mr_regwrite(sc, MPI3_SYSIF_IOC_CONFIG_OFFSET, ioc_config);
60812d1d418eSSumit Saxena 
60822d1d418eSSumit Saxena 	if (sc->facts.shutdown_timeout)
60832d1d418eSSumit Saxena 		timeout = sc->facts.shutdown_timeout * 10;
60842d1d418eSSumit Saxena 
60852d1d418eSSumit Saxena 	do {
60862d1d418eSSumit Saxena 		ioc_status = mpi3mr_regread(sc, MPI3_SYSIF_IOC_STATUS_OFFSET);
60872d1d418eSSumit Saxena 		if ((ioc_status & MPI3_SYSIF_IOC_STATUS_SHUTDOWN_MASK)
60882d1d418eSSumit Saxena 		    == MPI3_SYSIF_IOC_STATUS_SHUTDOWN_COMPLETE) {
60892d1d418eSSumit Saxena 			retval = 0;
60902d1d418eSSumit Saxena 			break;
60912d1d418eSSumit Saxena 		}
60922d1d418eSSumit Saxena 
60932d1d418eSSumit Saxena 		if (sc->unrecoverable)
60942d1d418eSSumit Saxena 			break;
60952d1d418eSSumit Saxena 
60962d1d418eSSumit Saxena 		if ((ioc_status & MPI3_SYSIF_IOC_STATUS_FAULT)) {
60972d1d418eSSumit Saxena 			mpi3mr_print_fault_info(sc);
60982d1d418eSSumit Saxena 
60992d1d418eSSumit Saxena 			if (retry >= MPI3MR_MAX_SHUTDOWN_RETRY_COUNT)
61002d1d418eSSumit Saxena 				break;
61012d1d418eSSumit Saxena 
61022d1d418eSSumit Saxena 			if (mpi3mr_issue_reset(sc,
61032d1d418eSSumit Saxena 			    MPI3_SYSIF_HOST_DIAG_RESET_ACTION_SOFT_RESET,
61042d1d418eSSumit Saxena 			    MPI3MR_RESET_FROM_CTLR_CLEANUP))
61052d1d418eSSumit Saxena 				break;
61062d1d418eSSumit Saxena 
61072d1d418eSSumit Saxena 			ioc_config = mpi3mr_regread(sc, MPI3_SYSIF_IOC_CONFIG_OFFSET);
61082d1d418eSSumit Saxena 			ioc_config |= MPI3_SYSIF_IOC_CONFIG_SHUTDOWN_NORMAL;
61092d1d418eSSumit Saxena 			ioc_config |= MPI3_SYSIF_IOC_CONFIG_DEVICE_SHUTDOWN_SEND_REQ;
61102d1d418eSSumit Saxena 
61112d1d418eSSumit Saxena 			mpi3mr_regwrite(sc, MPI3_SYSIF_IOC_CONFIG_OFFSET, ioc_config);
61122d1d418eSSumit Saxena 
61132d1d418eSSumit Saxena 			if (sc->facts.shutdown_timeout)
61142d1d418eSSumit Saxena 				timeout = sc->facts.shutdown_timeout * 10;
61152d1d418eSSumit Saxena 
61162d1d418eSSumit Saxena 			retry++;
61172d1d418eSSumit Saxena 		}
61182d1d418eSSumit Saxena 
61192d1d418eSSumit Saxena                 DELAY(100 * 1000);
61202d1d418eSSumit Saxena 
61212d1d418eSSumit Saxena 	} while (--timeout);
61222d1d418eSSumit Saxena 
61232d1d418eSSumit Saxena 	ioc_status = mpi3mr_regread(sc, MPI3_SYSIF_IOC_STATUS_OFFSET);
61242d1d418eSSumit Saxena 	ioc_config = mpi3mr_regread(sc, MPI3_SYSIF_IOC_CONFIG_OFFSET);
61252d1d418eSSumit Saxena 
61262d1d418eSSumit Saxena 	if (retval) {
61272d1d418eSSumit Saxena 		if ((ioc_status & MPI3_SYSIF_IOC_STATUS_SHUTDOWN_MASK)
61282d1d418eSSumit Saxena 		    == MPI3_SYSIF_IOC_STATUS_SHUTDOWN_IN_PROGRESS)
61292d1d418eSSumit Saxena 			mpi3mr_dprint(sc, MPI3MR_ERROR,
61302d1d418eSSumit Saxena 			    "shutdown still in progress after timeout\n");
61312d1d418eSSumit Saxena 	}
61322d1d418eSSumit Saxena 
61332d1d418eSSumit Saxena 	mpi3mr_dprint(sc, MPI3MR_INFO,
61342d1d418eSSumit Saxena 	    "ioc_status/ioc_config after %s shutdown is (0x%x)/(0x%x)\n",
61352d1d418eSSumit Saxena 	    (!retval)?"successful":"failed", ioc_status,
61362d1d418eSSumit Saxena 	    ioc_config);
61372d1d418eSSumit Saxena }
61382d1d418eSSumit Saxena 
61392d1d418eSSumit Saxena /**
61402d1d418eSSumit Saxena  * mpi3mr_cleanup_ioc - Cleanup controller
61412d1d418eSSumit Saxena  * @sc: Adapter instance reference
61422d1d418eSSumit Saxena 
61432d1d418eSSumit Saxena  * controller cleanup handler, Message unit reset or soft reset
61442d1d418eSSumit Saxena  * and shutdown notification is issued to the controller.
61452d1d418eSSumit Saxena  *
61462d1d418eSSumit Saxena  * Return: Nothing.
61472d1d418eSSumit Saxena  */
mpi3mr_cleanup_ioc(struct mpi3mr_softc * sc)61482d1d418eSSumit Saxena void mpi3mr_cleanup_ioc(struct mpi3mr_softc *sc)
61492d1d418eSSumit Saxena {
61502d1d418eSSumit Saxena 	enum mpi3mr_iocstate ioc_state;
61512d1d418eSSumit Saxena 
61522d1d418eSSumit Saxena 	mpi3mr_dprint(sc, MPI3MR_INFO, "cleaning up the controller\n");
61532d1d418eSSumit Saxena 	mpi3mr_disable_interrupts(sc);
61542d1d418eSSumit Saxena 
61552d1d418eSSumit Saxena 	ioc_state = mpi3mr_get_iocstate(sc);
61562d1d418eSSumit Saxena 
61572d1d418eSSumit Saxena 	if ((!sc->unrecoverable) && (!sc->reset_in_progress) &&
61582d1d418eSSumit Saxena 	    (ioc_state == MRIOC_STATE_READY)) {
61592d1d418eSSumit Saxena 		if (mpi3mr_mur_ioc(sc,
61602d1d418eSSumit Saxena 		    MPI3MR_RESET_FROM_CTLR_CLEANUP))
61612d1d418eSSumit Saxena 			mpi3mr_issue_reset(sc,
61622d1d418eSSumit Saxena 			    MPI3_SYSIF_HOST_DIAG_RESET_ACTION_SOFT_RESET,
61632d1d418eSSumit Saxena 			    MPI3MR_RESET_FROM_MUR_FAILURE);
61642d1d418eSSumit Saxena 		mpi3mr_issue_ioc_shutdown(sc);
61652d1d418eSSumit Saxena 	}
61662d1d418eSSumit Saxena 
61672d1d418eSSumit Saxena 	mpi3mr_dprint(sc, MPI3MR_INFO, "controller cleanup completed\n");
61682d1d418eSSumit Saxena }
6169