12d1d418eSSumit Saxena /* 22d1d418eSSumit Saxena * SPDX-License-Identifier: BSD-2-Clause 32d1d418eSSumit Saxena * 4*945c3ce4SChandrakanth 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 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 1172d1d418eSSumit Saxena init_completion(struct completion *completion) 1182d1d418eSSumit Saxena { 1192d1d418eSSumit Saxena completion->done = 0; 1202d1d418eSSumit Saxena } 1212d1d418eSSumit Saxena 1222d1d418eSSumit Saxena void 1232d1d418eSSumit Saxena complete(struct completion *completion) 1242d1d418eSSumit Saxena { 1252d1d418eSSumit Saxena completion->done = 1; 1262d1d418eSSumit Saxena wakeup(complete); 1272d1d418eSSumit Saxena } 1282d1d418eSSumit Saxena 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 } 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 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 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 */ 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 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 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 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 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 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 */ 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 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 */ 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 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 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 4582d1d418eSSumit Saxena void mpi3mr_enable_interrupts(struct mpi3mr_softc *sc) 4592d1d418eSSumit Saxena { 4602d1d418eSSumit Saxena sc->intr_enabled = 1; 4612d1d418eSSumit Saxena } 4622d1d418eSSumit Saxena 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 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 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 */ 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 */ 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 */ 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 */ 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 */ 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 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 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 */ 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 */ 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 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 */ 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 */ 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 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 */ 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 */ 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 */ 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 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 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 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 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 */ 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 21792d1d418eSSumit Saxena init_completion(&sc->init_cmds.completion); 21802d1d418eSSumit Saxena retval = mpi3mr_submit_admin_cmd(sc, &iocinit_req, 21812d1d418eSSumit Saxena sizeof(iocinit_req)); 21822d1d418eSSumit Saxena 21832d1d418eSSumit Saxena if (retval) { 21842d1d418eSSumit Saxena printf(IOCNAME "Issue IOCInit: Admin Post failed\n", 21852d1d418eSSumit Saxena sc->name); 21862d1d418eSSumit Saxena goto out_unlock; 21872d1d418eSSumit Saxena } 21882d1d418eSSumit Saxena 21892d1d418eSSumit Saxena wait_for_completion_timeout(&sc->init_cmds.completion, 21902d1d418eSSumit Saxena (MPI3MR_INTADMCMD_TIMEOUT)); 21912d1d418eSSumit Saxena if (!(sc->init_cmds.state & MPI3MR_CMD_COMPLETE)) { 21922d1d418eSSumit Saxena printf(IOCNAME "Issue IOCInit: command timed out\n", 21932d1d418eSSumit Saxena sc->name); 21942d1d418eSSumit Saxena mpi3mr_check_rh_fault_ioc(sc, 21952d1d418eSSumit Saxena MPI3MR_RESET_FROM_IOCINIT_TIMEOUT); 21962d1d418eSSumit Saxena sc->unrecoverable = 1; 21972d1d418eSSumit Saxena retval = -1; 21982d1d418eSSumit Saxena goto out_unlock; 21992d1d418eSSumit Saxena } 22002d1d418eSSumit Saxena 22012d1d418eSSumit Saxena if ((sc->init_cmds.ioc_status & MPI3_IOCSTATUS_STATUS_MASK) 22022d1d418eSSumit Saxena != MPI3_IOCSTATUS_SUCCESS ) { 22032d1d418eSSumit Saxena printf(IOCNAME "Issue IOCInit: Failed IOCStatus(0x%04x) " 22042d1d418eSSumit Saxena " Loginfo(0x%08x) \n" , sc->name, 22052d1d418eSSumit Saxena (sc->init_cmds.ioc_status & MPI3_IOCSTATUS_STATUS_MASK), 22062d1d418eSSumit Saxena sc->init_cmds.ioc_loginfo); 22072d1d418eSSumit Saxena retval = -1; 22082d1d418eSSumit Saxena goto out_unlock; 22092d1d418eSSumit Saxena } 22102d1d418eSSumit Saxena 22112d1d418eSSumit Saxena out_unlock: 22122d1d418eSSumit Saxena sc->init_cmds.state = MPI3MR_CMD_NOTUSED; 22132d1d418eSSumit Saxena mtx_unlock(&sc->init_cmds.completion.lock); 22142d1d418eSSumit Saxena 22152d1d418eSSumit Saxena out: 22162d1d418eSSumit Saxena if (drvr_info_phys != 0) 22172d1d418eSSumit Saxena bus_dmamap_unload(drvr_info_tag, drvr_info_map); 22182d1d418eSSumit Saxena if (drvr_info != NULL) 22192d1d418eSSumit Saxena bus_dmamem_free(drvr_info_tag, drvr_info, drvr_info_map); 22202d1d418eSSumit Saxena if (drvr_info_tag != NULL) 22212d1d418eSSumit Saxena bus_dma_tag_destroy(drvr_info_tag); 22222d1d418eSSumit Saxena return retval; 22232d1d418eSSumit Saxena } 22242d1d418eSSumit Saxena 22252d1d418eSSumit Saxena static void 22262d1d418eSSumit Saxena mpi3mr_display_ioc_info(struct mpi3mr_softc *sc) 22272d1d418eSSumit Saxena { 22282d1d418eSSumit Saxena int i = 0; 22292d1d418eSSumit Saxena char personality[16]; 22302d1d418eSSumit Saxena 22312d1d418eSSumit Saxena switch (sc->facts.personality) { 22322d1d418eSSumit Saxena case MPI3_IOCFACTS_FLAGS_PERSONALITY_EHBA: 22332d1d418eSSumit Saxena strcpy(personality, "Enhanced HBA"); 22342d1d418eSSumit Saxena break; 22352d1d418eSSumit Saxena case MPI3_IOCFACTS_FLAGS_PERSONALITY_RAID_DDR: 22362d1d418eSSumit Saxena strcpy(personality, "RAID"); 22372d1d418eSSumit Saxena break; 22382d1d418eSSumit Saxena default: 22392d1d418eSSumit Saxena strcpy(personality, "Unknown"); 22402d1d418eSSumit Saxena break; 22412d1d418eSSumit Saxena } 22422d1d418eSSumit Saxena 22432d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_INFO, "Current Personality: %s\n", personality); 22442d1d418eSSumit Saxena 224528a27434SWarner Losh mpi3mr_dprint(sc, MPI3MR_INFO, "%s\n", sc->fw_version); 22462d1d418eSSumit Saxena 22472d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_INFO, "Protocol=("); 22482d1d418eSSumit Saxena 22492d1d418eSSumit Saxena if (sc->facts.protocol_flags & 22502d1d418eSSumit Saxena MPI3_IOCFACTS_PROTOCOL_SCSI_INITIATOR) { 22512d1d418eSSumit Saxena printf("Initiator"); 22522d1d418eSSumit Saxena i++; 22532d1d418eSSumit Saxena } 22542d1d418eSSumit Saxena 22552d1d418eSSumit Saxena if (sc->facts.protocol_flags & 22562d1d418eSSumit Saxena MPI3_IOCFACTS_PROTOCOL_SCSI_TARGET) { 22572d1d418eSSumit Saxena printf("%sTarget", i ? "," : ""); 22582d1d418eSSumit Saxena i++; 22592d1d418eSSumit Saxena } 22602d1d418eSSumit Saxena 22612d1d418eSSumit Saxena if (sc->facts.protocol_flags & 22622d1d418eSSumit Saxena MPI3_IOCFACTS_PROTOCOL_NVME) { 22632d1d418eSSumit Saxena printf("%sNVMe attachment", i ? "," : ""); 22642d1d418eSSumit Saxena i++; 22652d1d418eSSumit Saxena } 22662d1d418eSSumit Saxena i = 0; 22672d1d418eSSumit Saxena printf("), "); 22682d1d418eSSumit Saxena printf("Capabilities=("); 22692d1d418eSSumit Saxena 22702d1d418eSSumit Saxena if (sc->facts.ioc_capabilities & 2271baabb919SChandrakanth patil MPI3_IOCFACTS_CAPABILITY_RAID_SUPPORTED) { 22722d1d418eSSumit Saxena printf("RAID"); 22732d1d418eSSumit Saxena i++; 22742d1d418eSSumit Saxena } 22752d1d418eSSumit Saxena 22762d1d418eSSumit Saxena printf(")\n"); 22772d1d418eSSumit Saxena } 22782d1d418eSSumit Saxena 22792d1d418eSSumit Saxena /** 22802d1d418eSSumit Saxena * mpi3mr_unmask_events - Unmask events in event mask bitmap 22812d1d418eSSumit Saxena * @sc: Adapter instance reference 22822d1d418eSSumit Saxena * @event: MPI event ID 22832d1d418eSSumit Saxena * 22842d1d418eSSumit Saxena * Un mask the specific event by resetting the event_mask 22852d1d418eSSumit Saxena * bitmap. 22862d1d418eSSumit Saxena * 22872d1d418eSSumit Saxena * Return: None. 22882d1d418eSSumit Saxena */ 22892d1d418eSSumit Saxena static void mpi3mr_unmask_events(struct mpi3mr_softc *sc, U16 event) 22902d1d418eSSumit Saxena { 22912d1d418eSSumit Saxena U32 desired_event; 22922d1d418eSSumit Saxena 22932d1d418eSSumit Saxena if (event >= 128) 22942d1d418eSSumit Saxena return; 22952d1d418eSSumit Saxena 22962d1d418eSSumit Saxena desired_event = (1 << (event % 32)); 22972d1d418eSSumit Saxena 22982d1d418eSSumit Saxena if (event < 32) 22992d1d418eSSumit Saxena sc->event_masks[0] &= ~desired_event; 23002d1d418eSSumit Saxena else if (event < 64) 23012d1d418eSSumit Saxena sc->event_masks[1] &= ~desired_event; 23022d1d418eSSumit Saxena else if (event < 96) 23032d1d418eSSumit Saxena sc->event_masks[2] &= ~desired_event; 23042d1d418eSSumit Saxena else if (event < 128) 23052d1d418eSSumit Saxena sc->event_masks[3] &= ~desired_event; 23062d1d418eSSumit Saxena } 23072d1d418eSSumit Saxena 23082d1d418eSSumit Saxena static void mpi3mr_set_events_mask(struct mpi3mr_softc *sc) 23092d1d418eSSumit Saxena { 23102d1d418eSSumit Saxena int i; 23112d1d418eSSumit Saxena for (i = 0; i < MPI3_EVENT_NOTIFY_EVENTMASK_WORDS; i++) 23122d1d418eSSumit Saxena sc->event_masks[i] = -1; 23132d1d418eSSumit Saxena 23142d1d418eSSumit Saxena mpi3mr_unmask_events(sc, MPI3_EVENT_DEVICE_ADDED); 23152d1d418eSSumit Saxena mpi3mr_unmask_events(sc, MPI3_EVENT_DEVICE_INFO_CHANGED); 23162d1d418eSSumit Saxena mpi3mr_unmask_events(sc, MPI3_EVENT_DEVICE_STATUS_CHANGE); 23172d1d418eSSumit Saxena 23182d1d418eSSumit Saxena mpi3mr_unmask_events(sc, MPI3_EVENT_ENCL_DEVICE_STATUS_CHANGE); 23192d1d418eSSumit Saxena 23202d1d418eSSumit Saxena mpi3mr_unmask_events(sc, MPI3_EVENT_SAS_TOPOLOGY_CHANGE_LIST); 23212d1d418eSSumit Saxena mpi3mr_unmask_events(sc, MPI3_EVENT_SAS_DISCOVERY); 23222d1d418eSSumit Saxena mpi3mr_unmask_events(sc, MPI3_EVENT_SAS_DEVICE_DISCOVERY_ERROR); 23232d1d418eSSumit Saxena mpi3mr_unmask_events(sc, MPI3_EVENT_SAS_BROADCAST_PRIMITIVE); 23242d1d418eSSumit Saxena 23252d1d418eSSumit Saxena mpi3mr_unmask_events(sc, MPI3_EVENT_PCIE_TOPOLOGY_CHANGE_LIST); 23262d1d418eSSumit Saxena mpi3mr_unmask_events(sc, MPI3_EVENT_PCIE_ENUMERATION); 23272d1d418eSSumit Saxena 23282d1d418eSSumit Saxena mpi3mr_unmask_events(sc, MPI3_EVENT_PREPARE_FOR_RESET); 23292d1d418eSSumit Saxena mpi3mr_unmask_events(sc, MPI3_EVENT_CABLE_MGMT); 23302d1d418eSSumit Saxena mpi3mr_unmask_events(sc, MPI3_EVENT_ENERGY_PACK_CHANGE); 23312d1d418eSSumit Saxena } 23322d1d418eSSumit Saxena 23332d1d418eSSumit Saxena /** 23342d1d418eSSumit Saxena * mpi3mr_issue_event_notification - Send event notification 23352d1d418eSSumit Saxena * @sc: Adapter instance reference 23362d1d418eSSumit Saxena * 23372d1d418eSSumit Saxena * Issue event notification MPI request through admin queue and 23382d1d418eSSumit Saxena * wait for the completion of it or time out. 23392d1d418eSSumit Saxena * 23402d1d418eSSumit Saxena * Return: 0 on success, non-zero on failures. 23412d1d418eSSumit Saxena */ 23422d1d418eSSumit Saxena int mpi3mr_issue_event_notification(struct mpi3mr_softc *sc) 23432d1d418eSSumit Saxena { 23442d1d418eSSumit Saxena Mpi3EventNotificationRequest_t evtnotify_req; 23452d1d418eSSumit Saxena int retval = 0; 23462d1d418eSSumit Saxena U8 i; 23472d1d418eSSumit Saxena 23482d1d418eSSumit Saxena memset(&evtnotify_req, 0, sizeof(evtnotify_req)); 23492d1d418eSSumit Saxena mtx_lock(&sc->init_cmds.completion.lock); 23502d1d418eSSumit Saxena if (sc->init_cmds.state & MPI3MR_CMD_PENDING) { 23512d1d418eSSumit Saxena retval = -1; 23522d1d418eSSumit Saxena printf(IOCNAME "Issue EvtNotify: Init command is in use\n", 23532d1d418eSSumit Saxena sc->name); 23542d1d418eSSumit Saxena mtx_unlock(&sc->init_cmds.completion.lock); 23552d1d418eSSumit Saxena goto out; 23562d1d418eSSumit Saxena } 23572d1d418eSSumit Saxena sc->init_cmds.state = MPI3MR_CMD_PENDING; 23582d1d418eSSumit Saxena sc->init_cmds.is_waiting = 1; 23592d1d418eSSumit Saxena sc->init_cmds.callback = NULL; 23602d1d418eSSumit Saxena evtnotify_req.HostTag = (MPI3MR_HOSTTAG_INITCMDS); 23612d1d418eSSumit Saxena evtnotify_req.Function = MPI3_FUNCTION_EVENT_NOTIFICATION; 23622d1d418eSSumit Saxena for (i = 0; i < MPI3_EVENT_NOTIFY_EVENTMASK_WORDS; i++) 23632d1d418eSSumit Saxena evtnotify_req.EventMasks[i] = 23642d1d418eSSumit Saxena (sc->event_masks[i]); 23652d1d418eSSumit Saxena init_completion(&sc->init_cmds.completion); 23662d1d418eSSumit Saxena retval = mpi3mr_submit_admin_cmd(sc, &evtnotify_req, 23672d1d418eSSumit Saxena sizeof(evtnotify_req)); 23682d1d418eSSumit Saxena if (retval) { 23692d1d418eSSumit Saxena printf(IOCNAME "Issue EvtNotify: Admin Post failed\n", 23702d1d418eSSumit Saxena sc->name); 23712d1d418eSSumit Saxena goto out_unlock; 23722d1d418eSSumit Saxena } 23732d1d418eSSumit Saxena 23742d1d418eSSumit Saxena poll_for_command_completion(sc, 23752d1d418eSSumit Saxena &sc->init_cmds, 23762d1d418eSSumit Saxena (MPI3MR_INTADMCMD_TIMEOUT)); 23772d1d418eSSumit Saxena if (!(sc->init_cmds.state & MPI3MR_CMD_COMPLETE)) { 23782d1d418eSSumit Saxena printf(IOCNAME "Issue EvtNotify: command timed out\n", 23792d1d418eSSumit Saxena sc->name); 23802d1d418eSSumit Saxena mpi3mr_check_rh_fault_ioc(sc, 23812d1d418eSSumit Saxena MPI3MR_RESET_FROM_EVTNOTIFY_TIMEOUT); 23822d1d418eSSumit Saxena retval = -1; 23832d1d418eSSumit Saxena goto out_unlock; 23842d1d418eSSumit Saxena } 23852d1d418eSSumit Saxena 23862d1d418eSSumit Saxena if ((sc->init_cmds.ioc_status & MPI3_IOCSTATUS_STATUS_MASK) 23872d1d418eSSumit Saxena != MPI3_IOCSTATUS_SUCCESS ) { 23882d1d418eSSumit Saxena printf(IOCNAME "Issue EvtNotify: Failed IOCStatus(0x%04x) " 23892d1d418eSSumit Saxena " Loginfo(0x%08x) \n" , sc->name, 23902d1d418eSSumit Saxena (sc->init_cmds.ioc_status & MPI3_IOCSTATUS_STATUS_MASK), 23912d1d418eSSumit Saxena sc->init_cmds.ioc_loginfo); 23922d1d418eSSumit Saxena retval = -1; 23932d1d418eSSumit Saxena goto out_unlock; 23942d1d418eSSumit Saxena } 23952d1d418eSSumit Saxena 23962d1d418eSSumit Saxena out_unlock: 23972d1d418eSSumit Saxena sc->init_cmds.state = MPI3MR_CMD_NOTUSED; 23982d1d418eSSumit Saxena mtx_unlock(&sc->init_cmds.completion.lock); 23992d1d418eSSumit Saxena 24002d1d418eSSumit Saxena out: 24012d1d418eSSumit Saxena return retval; 24022d1d418eSSumit Saxena } 24032d1d418eSSumit Saxena 24042d1d418eSSumit Saxena int 24052d1d418eSSumit Saxena mpi3mr_register_events(struct mpi3mr_softc *sc) 24062d1d418eSSumit Saxena { 24072d1d418eSSumit Saxena int error; 24082d1d418eSSumit Saxena 24092d1d418eSSumit Saxena mpi3mr_set_events_mask(sc); 24102d1d418eSSumit Saxena 24112d1d418eSSumit Saxena error = mpi3mr_issue_event_notification(sc); 24122d1d418eSSumit Saxena 24132d1d418eSSumit Saxena if (error) { 24142d1d418eSSumit Saxena printf(IOCNAME "Failed to issue event notification %d\n", 24152d1d418eSSumit Saxena sc->name, error); 24162d1d418eSSumit Saxena } 24172d1d418eSSumit Saxena 24182d1d418eSSumit Saxena return error; 24192d1d418eSSumit Saxena } 24202d1d418eSSumit Saxena 24212d1d418eSSumit Saxena /** 24222d1d418eSSumit Saxena * mpi3mr_process_event_ack - Process event acknowledgment 24232d1d418eSSumit Saxena * @sc: Adapter instance reference 24242d1d418eSSumit Saxena * @event: MPI3 event ID 24252d1d418eSSumit Saxena * @event_ctx: Event context 24262d1d418eSSumit Saxena * 24272d1d418eSSumit Saxena * Send event acknowledgement through admin queue and wait for 24282d1d418eSSumit Saxena * it to complete. 24292d1d418eSSumit Saxena * 24302d1d418eSSumit Saxena * Return: 0 on success, non-zero on failures. 24312d1d418eSSumit Saxena */ 24322d1d418eSSumit Saxena int mpi3mr_process_event_ack(struct mpi3mr_softc *sc, U8 event, 24332d1d418eSSumit Saxena U32 event_ctx) 24342d1d418eSSumit Saxena { 24352d1d418eSSumit Saxena Mpi3EventAckRequest_t evtack_req; 24362d1d418eSSumit Saxena int retval = 0; 24372d1d418eSSumit Saxena 24382d1d418eSSumit Saxena memset(&evtack_req, 0, sizeof(evtack_req)); 24392d1d418eSSumit Saxena mtx_lock(&sc->init_cmds.completion.lock); 24402d1d418eSSumit Saxena if (sc->init_cmds.state & MPI3MR_CMD_PENDING) { 24412d1d418eSSumit Saxena retval = -1; 24422d1d418eSSumit Saxena printf(IOCNAME "Issue EvtAck: Init command is in use\n", 24432d1d418eSSumit Saxena sc->name); 24442d1d418eSSumit Saxena mtx_unlock(&sc->init_cmds.completion.lock); 24452d1d418eSSumit Saxena goto out; 24462d1d418eSSumit Saxena } 24472d1d418eSSumit Saxena sc->init_cmds.state = MPI3MR_CMD_PENDING; 24482d1d418eSSumit Saxena sc->init_cmds.is_waiting = 1; 24492d1d418eSSumit Saxena sc->init_cmds.callback = NULL; 24502d1d418eSSumit Saxena evtack_req.HostTag = htole16(MPI3MR_HOSTTAG_INITCMDS); 24512d1d418eSSumit Saxena evtack_req.Function = MPI3_FUNCTION_EVENT_ACK; 24522d1d418eSSumit Saxena evtack_req.Event = event; 24532d1d418eSSumit Saxena evtack_req.EventContext = htole32(event_ctx); 24542d1d418eSSumit Saxena 24552d1d418eSSumit Saxena init_completion(&sc->init_cmds.completion); 24562d1d418eSSumit Saxena retval = mpi3mr_submit_admin_cmd(sc, &evtack_req, 24572d1d418eSSumit Saxena sizeof(evtack_req)); 24582d1d418eSSumit Saxena if (retval) { 24592d1d418eSSumit Saxena printf(IOCNAME "Issue EvtAck: Admin Post failed\n", 24602d1d418eSSumit Saxena sc->name); 24612d1d418eSSumit Saxena goto out_unlock; 24622d1d418eSSumit Saxena } 24632d1d418eSSumit Saxena 24642d1d418eSSumit Saxena wait_for_completion_timeout(&sc->init_cmds.completion, 24652d1d418eSSumit Saxena (MPI3MR_INTADMCMD_TIMEOUT)); 24662d1d418eSSumit Saxena if (!(sc->init_cmds.state & MPI3MR_CMD_COMPLETE)) { 24672d1d418eSSumit Saxena printf(IOCNAME "Issue EvtAck: command timed out\n", 24682d1d418eSSumit Saxena sc->name); 24692d1d418eSSumit Saxena retval = -1; 24702d1d418eSSumit Saxena goto out_unlock; 24712d1d418eSSumit Saxena } 24722d1d418eSSumit Saxena 24732d1d418eSSumit Saxena if ((sc->init_cmds.ioc_status & MPI3_IOCSTATUS_STATUS_MASK) 24742d1d418eSSumit Saxena != MPI3_IOCSTATUS_SUCCESS ) { 24752d1d418eSSumit Saxena printf(IOCNAME "Issue EvtAck: Failed IOCStatus(0x%04x) " 24762d1d418eSSumit Saxena " Loginfo(0x%08x) \n" , sc->name, 24772d1d418eSSumit Saxena (sc->init_cmds.ioc_status & MPI3_IOCSTATUS_STATUS_MASK), 24782d1d418eSSumit Saxena sc->init_cmds.ioc_loginfo); 24792d1d418eSSumit Saxena retval = -1; 24802d1d418eSSumit Saxena goto out_unlock; 24812d1d418eSSumit Saxena } 24822d1d418eSSumit Saxena 24832d1d418eSSumit Saxena out_unlock: 24842d1d418eSSumit Saxena sc->init_cmds.state = MPI3MR_CMD_NOTUSED; 24852d1d418eSSumit Saxena mtx_unlock(&sc->init_cmds.completion.lock); 24862d1d418eSSumit Saxena 24872d1d418eSSumit Saxena out: 24882d1d418eSSumit Saxena return retval; 24892d1d418eSSumit Saxena } 24902d1d418eSSumit Saxena 24912d1d418eSSumit Saxena 24922d1d418eSSumit Saxena static int mpi3mr_alloc_chain_bufs(struct mpi3mr_softc *sc) 24932d1d418eSSumit Saxena { 24942d1d418eSSumit Saxena int retval = 0; 24952d1d418eSSumit Saxena U32 sz, i; 24962d1d418eSSumit Saxena U16 num_chains; 24972d1d418eSSumit Saxena 24982d1d418eSSumit Saxena num_chains = sc->max_host_ios; 24992d1d418eSSumit Saxena 25002d1d418eSSumit Saxena sc->chain_buf_count = num_chains; 25012d1d418eSSumit Saxena sz = sizeof(struct mpi3mr_chain) * num_chains; 25022d1d418eSSumit Saxena 25032d1d418eSSumit Saxena sc->chain_sgl_list = malloc(sz, M_MPI3MR, M_NOWAIT | M_ZERO); 25042d1d418eSSumit Saxena 25052d1d418eSSumit Saxena if (!sc->chain_sgl_list) { 25062d1d418eSSumit Saxena printf(IOCNAME "Cannot allocate memory for chain SGL list\n", 25072d1d418eSSumit Saxena sc->name); 25082d1d418eSSumit Saxena retval = -1; 25092d1d418eSSumit Saxena goto out_failed; 25102d1d418eSSumit Saxena } 25112d1d418eSSumit Saxena 25122d1d418eSSumit Saxena sz = MPI3MR_CHAINSGE_SIZE; 25132d1d418eSSumit Saxena 25142d1d418eSSumit Saxena if (bus_dma_tag_create(sc->mpi3mr_parent_dmat, /* parent */ 25152d1d418eSSumit Saxena 4096, 0, /* algnmnt, boundary */ 2516ee7c431cSWarner Losh sc->dma_loaddr, /* lowaddr */ 25171ec7c672SWarner Losh BUS_SPACE_MAXADDR, /* highaddr */ 25182d1d418eSSumit Saxena NULL, NULL, /* filter, filterarg */ 25192d1d418eSSumit Saxena sz, /* maxsize */ 25202d1d418eSSumit Saxena 1, /* nsegments */ 25212d1d418eSSumit Saxena sz, /* maxsegsize */ 25222d1d418eSSumit Saxena 0, /* flags */ 25232d1d418eSSumit Saxena NULL, NULL, /* lockfunc, lockarg */ 25242d1d418eSSumit Saxena &sc->chain_sgl_list_tag)) { 25252d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_ERROR, "Cannot allocate Chain buffer DMA tag\n"); 25262d1d418eSSumit Saxena return (ENOMEM); 25272d1d418eSSumit Saxena } 25282d1d418eSSumit Saxena 25292d1d418eSSumit Saxena for (i = 0; i < num_chains; i++) { 25302d1d418eSSumit Saxena if (bus_dmamem_alloc(sc->chain_sgl_list_tag, (void **)&sc->chain_sgl_list[i].buf, 25312d1d418eSSumit Saxena BUS_DMA_NOWAIT, &sc->chain_sgl_list[i].buf_dmamap)) { 25322d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_ERROR, "Func: %s line: %d DMA mem alloc failed\n", 25332d1d418eSSumit Saxena __func__, __LINE__); 25342d1d418eSSumit Saxena return (ENOMEM); 25352d1d418eSSumit Saxena } 25362d1d418eSSumit Saxena 25372d1d418eSSumit Saxena bzero(sc->chain_sgl_list[i].buf, sz); 25382d1d418eSSumit Saxena bus_dmamap_load(sc->chain_sgl_list_tag, sc->chain_sgl_list[i].buf_dmamap, sc->chain_sgl_list[i].buf, sz, 253939a3e6a8SAlexander Motin mpi3mr_memaddr_cb, &sc->chain_sgl_list[i].buf_phys, BUS_DMA_NOWAIT); 25402d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_XINFO, "Func: %s line: %d phys addr= %#016jx size= %d\n", 25412d1d418eSSumit Saxena __func__, __LINE__, (uintmax_t)sc->chain_sgl_list[i].buf_phys, sz); 25422d1d418eSSumit Saxena } 25432d1d418eSSumit Saxena 25442d1d418eSSumit Saxena sc->chain_bitmap_sz = MPI3MR_DIV_ROUND_UP(num_chains, 8); 25452d1d418eSSumit Saxena 25462d1d418eSSumit Saxena sc->chain_bitmap = malloc(sc->chain_bitmap_sz, M_MPI3MR, M_NOWAIT | M_ZERO); 25472d1d418eSSumit Saxena if (!sc->chain_bitmap) { 25482d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_INFO, "Cannot alloc memory for chain bitmap\n"); 25492d1d418eSSumit Saxena retval = -1; 25502d1d418eSSumit Saxena goto out_failed; 25512d1d418eSSumit Saxena } 25522d1d418eSSumit Saxena return retval; 25532d1d418eSSumit Saxena 25542d1d418eSSumit Saxena out_failed: 25552d1d418eSSumit Saxena for (i = 0; i < num_chains; i++) { 25562d1d418eSSumit Saxena if (sc->chain_sgl_list[i].buf_phys != 0) 25572d1d418eSSumit Saxena bus_dmamap_unload(sc->chain_sgl_list_tag, sc->chain_sgl_list[i].buf_dmamap); 25582d1d418eSSumit Saxena if (sc->chain_sgl_list[i].buf != NULL) 25592d1d418eSSumit Saxena bus_dmamem_free(sc->chain_sgl_list_tag, sc->chain_sgl_list[i].buf, sc->chain_sgl_list[i].buf_dmamap); 25602d1d418eSSumit Saxena } 25612d1d418eSSumit Saxena if (sc->chain_sgl_list_tag != NULL) 25622d1d418eSSumit Saxena bus_dma_tag_destroy(sc->chain_sgl_list_tag); 25632d1d418eSSumit Saxena return retval; 25642d1d418eSSumit Saxena } 25652d1d418eSSumit Saxena 25662d1d418eSSumit Saxena static int mpi3mr_pel_alloc(struct mpi3mr_softc *sc) 25672d1d418eSSumit Saxena { 25682d1d418eSSumit Saxena int retval = 0; 25692d1d418eSSumit Saxena 25702d1d418eSSumit Saxena if (!sc->pel_cmds.reply) { 25712d1d418eSSumit Saxena sc->pel_cmds.reply = malloc(sc->reply_sz, M_MPI3MR, M_NOWAIT | M_ZERO); 25722d1d418eSSumit Saxena if (!sc->pel_cmds.reply) { 25732d1d418eSSumit Saxena printf(IOCNAME "Cannot allocate memory for pel_cmds.reply\n", 25742d1d418eSSumit Saxena sc->name); 25752d1d418eSSumit Saxena goto out_failed; 25762d1d418eSSumit Saxena } 25772d1d418eSSumit Saxena } 25782d1d418eSSumit Saxena 25792d1d418eSSumit Saxena if (!sc->pel_abort_cmd.reply) { 25802d1d418eSSumit Saxena sc->pel_abort_cmd.reply = malloc(sc->reply_sz, M_MPI3MR, M_NOWAIT | M_ZERO); 25812d1d418eSSumit Saxena if (!sc->pel_abort_cmd.reply) { 25822d1d418eSSumit Saxena printf(IOCNAME "Cannot allocate memory for pel_abort_cmd.reply\n", 25832d1d418eSSumit Saxena sc->name); 25842d1d418eSSumit Saxena goto out_failed; 25852d1d418eSSumit Saxena } 25862d1d418eSSumit Saxena } 25872d1d418eSSumit Saxena 25882d1d418eSSumit Saxena if (!sc->pel_seq_number) { 25892d1d418eSSumit Saxena sc->pel_seq_number_sz = sizeof(Mpi3PELSeq_t); 25902d1d418eSSumit Saxena if (bus_dma_tag_create(sc->mpi3mr_parent_dmat, /* parent */ 25912d1d418eSSumit Saxena 4, 0, /* alignment, boundary */ 2592ee7c431cSWarner Losh sc->dma_loaddr, /* lowaddr */ 25931ec7c672SWarner Losh BUS_SPACE_MAXADDR, /* highaddr */ 25942d1d418eSSumit Saxena NULL, NULL, /* filter, filterarg */ 25952d1d418eSSumit Saxena sc->pel_seq_number_sz, /* maxsize */ 25962d1d418eSSumit Saxena 1, /* nsegments */ 25972d1d418eSSumit Saxena sc->pel_seq_number_sz, /* maxsegsize */ 25982d1d418eSSumit Saxena 0, /* flags */ 25992d1d418eSSumit Saxena NULL, NULL, /* lockfunc, lockarg */ 26002d1d418eSSumit Saxena &sc->pel_seq_num_dmatag)) { 26012d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_ERROR, "Cannot create PEL seq number dma memory tag\n"); 26022d1d418eSSumit Saxena retval = -ENOMEM; 26032d1d418eSSumit Saxena goto out_failed; 26042d1d418eSSumit Saxena } 26052d1d418eSSumit Saxena 26062d1d418eSSumit Saxena if (bus_dmamem_alloc(sc->pel_seq_num_dmatag, (void **)&sc->pel_seq_number, 26072d1d418eSSumit Saxena BUS_DMA_NOWAIT, &sc->pel_seq_num_dmamap)) { 26082d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_ERROR, "Cannot allocate PEL seq number kernel buffer dma memory\n"); 26092d1d418eSSumit Saxena retval = -ENOMEM; 26102d1d418eSSumit Saxena goto out_failed; 26112d1d418eSSumit Saxena } 26122d1d418eSSumit Saxena 26132d1d418eSSumit Saxena bzero(sc->pel_seq_number, sc->pel_seq_number_sz); 26142d1d418eSSumit Saxena 26152d1d418eSSumit Saxena bus_dmamap_load(sc->pel_seq_num_dmatag, sc->pel_seq_num_dmamap, sc->pel_seq_number, 261639a3e6a8SAlexander Motin sc->pel_seq_number_sz, mpi3mr_memaddr_cb, &sc->pel_seq_number_dma, BUS_DMA_NOWAIT); 26172d1d418eSSumit Saxena 26182d1d418eSSumit Saxena if (!sc->pel_seq_number) { 26192d1d418eSSumit Saxena printf(IOCNAME "%s:%d Cannot load PEL seq number dma memory for size: %d\n", sc->name, 26202d1d418eSSumit Saxena __func__, __LINE__, sc->pel_seq_number_sz); 26212d1d418eSSumit Saxena retval = -ENOMEM; 26222d1d418eSSumit Saxena goto out_failed; 26232d1d418eSSumit Saxena } 26242d1d418eSSumit Saxena } 26252d1d418eSSumit Saxena 26262d1d418eSSumit Saxena out_failed: 26272d1d418eSSumit Saxena return retval; 26282d1d418eSSumit Saxena } 26292d1d418eSSumit Saxena 26302d1d418eSSumit Saxena /** 26312d1d418eSSumit Saxena * mpi3mr_validate_fw_update - validate IOCFacts post adapter reset 26322d1d418eSSumit Saxena * @sc: Adapter instance reference 26332d1d418eSSumit Saxena * 26342d1d418eSSumit Saxena * Return zero if the new IOCFacts is compatible with previous values 26352d1d418eSSumit Saxena * else return appropriate error 26362d1d418eSSumit Saxena */ 26372d1d418eSSumit Saxena static int 26382d1d418eSSumit Saxena mpi3mr_validate_fw_update(struct mpi3mr_softc *sc) 26392d1d418eSSumit Saxena { 26402d1d418eSSumit Saxena U16 dev_handle_bitmap_sz; 26412d1d418eSSumit Saxena U8 *removepend_bitmap; 26422d1d418eSSumit Saxena 26432d1d418eSSumit Saxena if (sc->facts.reply_sz > sc->reply_sz) { 26442d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_ERROR, 26452d1d418eSSumit Saxena "Cannot increase reply size from %d to %d\n", 26462d1d418eSSumit Saxena sc->reply_sz, sc->reply_sz); 26472d1d418eSSumit Saxena return -EPERM; 26482d1d418eSSumit Saxena } 26492d1d418eSSumit Saxena 26502d1d418eSSumit Saxena if (sc->num_io_throttle_group != sc->facts.max_io_throttle_group) { 26512d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_ERROR, 26522d1d418eSSumit Saxena "max io throttle group doesn't match old(%d), new(%d)\n", 26532d1d418eSSumit Saxena sc->num_io_throttle_group, 26542d1d418eSSumit Saxena sc->facts.max_io_throttle_group); 26552d1d418eSSumit Saxena return -EPERM; 26562d1d418eSSumit Saxena } 26572d1d418eSSumit Saxena 26582d1d418eSSumit Saxena if (sc->facts.max_op_reply_q < sc->num_queues) { 26592d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_ERROR, 26602d1d418eSSumit Saxena "Cannot reduce number of operational reply queues from %d to %d\n", 26612d1d418eSSumit Saxena sc->num_queues, 26622d1d418eSSumit Saxena sc->facts.max_op_reply_q); 26632d1d418eSSumit Saxena return -EPERM; 26642d1d418eSSumit Saxena } 26652d1d418eSSumit Saxena 26662d1d418eSSumit Saxena if (sc->facts.max_op_req_q < sc->num_queues) { 26672d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_ERROR, 26682d1d418eSSumit Saxena "Cannot reduce number of operational request queues from %d to %d\n", 26692d1d418eSSumit Saxena sc->num_queues, sc->facts.max_op_req_q); 26702d1d418eSSumit Saxena return -EPERM; 26712d1d418eSSumit Saxena } 26722d1d418eSSumit Saxena 26732d1d418eSSumit Saxena dev_handle_bitmap_sz = MPI3MR_DIV_ROUND_UP(sc->facts.max_devhandle, 8); 26742d1d418eSSumit Saxena 26752d1d418eSSumit Saxena if (dev_handle_bitmap_sz > sc->dev_handle_bitmap_sz) { 26762d1d418eSSumit Saxena removepend_bitmap = realloc(sc->removepend_bitmap, 26772d1d418eSSumit Saxena dev_handle_bitmap_sz, M_MPI3MR, M_NOWAIT); 26782d1d418eSSumit Saxena 26792d1d418eSSumit Saxena if (!removepend_bitmap) { 26802d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_ERROR, 26812d1d418eSSumit Saxena "failed to increase removepend_bitmap sz from: %d to %d\n", 26822d1d418eSSumit Saxena sc->dev_handle_bitmap_sz, dev_handle_bitmap_sz); 26832d1d418eSSumit Saxena return -ENOMEM; 26842d1d418eSSumit Saxena } 26852d1d418eSSumit Saxena 26862d1d418eSSumit Saxena memset(removepend_bitmap + sc->dev_handle_bitmap_sz, 0, 26872d1d418eSSumit Saxena dev_handle_bitmap_sz - sc->dev_handle_bitmap_sz); 26882d1d418eSSumit Saxena sc->removepend_bitmap = removepend_bitmap; 26892d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_INFO, 26902d1d418eSSumit Saxena "increased dev_handle_bitmap_sz from %d to %d\n", 26912d1d418eSSumit Saxena sc->dev_handle_bitmap_sz, dev_handle_bitmap_sz); 26922d1d418eSSumit Saxena sc->dev_handle_bitmap_sz = dev_handle_bitmap_sz; 26932d1d418eSSumit Saxena } 26942d1d418eSSumit Saxena 26952d1d418eSSumit Saxena return 0; 26962d1d418eSSumit Saxena } 26972d1d418eSSumit Saxena 26982d1d418eSSumit Saxena /* 26992d1d418eSSumit Saxena * mpi3mr_initialize_ioc - Controller initialization 27002d1d418eSSumit Saxena * @dev: pointer to device struct 27012d1d418eSSumit Saxena * 27022d1d418eSSumit Saxena * This function allocates the controller wide resources and brings 27032d1d418eSSumit Saxena * the controller to operational state 27042d1d418eSSumit Saxena * 27052d1d418eSSumit Saxena * Return: 0 on success and proper error codes on failure 27062d1d418eSSumit Saxena */ 27072d1d418eSSumit Saxena int mpi3mr_initialize_ioc(struct mpi3mr_softc *sc, U8 init_type) 27082d1d418eSSumit Saxena { 27092d1d418eSSumit Saxena int retval = 0; 27102d1d418eSSumit Saxena enum mpi3mr_iocstate ioc_state; 27112d1d418eSSumit Saxena U64 ioc_info; 27122d1d418eSSumit Saxena U32 ioc_status, ioc_control, i, timeout; 27132d1d418eSSumit Saxena Mpi3IOCFactsData_t facts_data; 27142d1d418eSSumit Saxena char str[32]; 27152d1d418eSSumit Saxena U32 size; 27162d1d418eSSumit Saxena 27172d1d418eSSumit Saxena sc->cpu_count = mp_ncpus; 27182d1d418eSSumit Saxena 27192d1d418eSSumit Saxena ioc_status = mpi3mr_regread(sc, MPI3_SYSIF_IOC_STATUS_OFFSET); 27202d1d418eSSumit Saxena ioc_control = mpi3mr_regread(sc, MPI3_SYSIF_IOC_CONFIG_OFFSET); 27212d1d418eSSumit Saxena ioc_info = mpi3mr_regread64(sc, MPI3_SYSIF_IOC_INFO_LOW_OFFSET); 27222d1d418eSSumit Saxena 27232d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_INFO, "SOD ioc_status: 0x%x ioc_control: 0x%x " 27242d1d418eSSumit Saxena "ioc_info: 0x%lx\n", ioc_status, ioc_control, ioc_info); 27252d1d418eSSumit Saxena 27262d1d418eSSumit Saxena /*The timeout value is in 2sec unit, changing it to seconds*/ 27272d1d418eSSumit Saxena sc->ready_timeout = 27282d1d418eSSumit Saxena ((ioc_info & MPI3_SYSIF_IOC_INFO_LOW_TIMEOUT_MASK) >> 27292d1d418eSSumit Saxena MPI3_SYSIF_IOC_INFO_LOW_TIMEOUT_SHIFT) * 2; 27302d1d418eSSumit Saxena 27312d1d418eSSumit Saxena ioc_state = mpi3mr_get_iocstate(sc); 27322d1d418eSSumit Saxena 27332d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_INFO, "IOC state: %s IOC ready timeout: %d\n", 27342d1d418eSSumit Saxena mpi3mr_iocstate_name(ioc_state), sc->ready_timeout); 27352d1d418eSSumit Saxena 27362d1d418eSSumit Saxena if (ioc_state == MRIOC_STATE_BECOMING_READY || 27372d1d418eSSumit Saxena ioc_state == MRIOC_STATE_RESET_REQUESTED) { 27382d1d418eSSumit Saxena timeout = sc->ready_timeout * 10; 27392d1d418eSSumit Saxena do { 27402d1d418eSSumit Saxena DELAY(1000 * 100); 27412d1d418eSSumit Saxena } while (--timeout); 27422d1d418eSSumit Saxena 27432d1d418eSSumit Saxena ioc_state = mpi3mr_get_iocstate(sc); 27442d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_INFO, 27452d1d418eSSumit Saxena "IOC in %s state after waiting for reset time\n", 27462d1d418eSSumit Saxena mpi3mr_iocstate_name(ioc_state)); 27472d1d418eSSumit Saxena } 27482d1d418eSSumit Saxena 27492d1d418eSSumit Saxena if (ioc_state == MRIOC_STATE_READY) { 27502d1d418eSSumit Saxena retval = mpi3mr_mur_ioc(sc, MPI3MR_RESET_FROM_BRINGUP); 27512d1d418eSSumit Saxena if (retval) { 27522d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_ERROR, "Failed to MU reset IOC, error 0x%x\n", 27532d1d418eSSumit Saxena retval); 27542d1d418eSSumit Saxena } 27552d1d418eSSumit Saxena ioc_state = mpi3mr_get_iocstate(sc); 27562d1d418eSSumit Saxena } 27572d1d418eSSumit Saxena 27582d1d418eSSumit Saxena if (ioc_state != MRIOC_STATE_RESET) { 27592d1d418eSSumit Saxena mpi3mr_print_fault_info(sc); 27602d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_ERROR, "issuing soft reset to bring to reset state\n"); 27612d1d418eSSumit Saxena retval = mpi3mr_issue_reset(sc, 27622d1d418eSSumit Saxena MPI3_SYSIF_HOST_DIAG_RESET_ACTION_SOFT_RESET, 27632d1d418eSSumit Saxena MPI3MR_RESET_FROM_BRINGUP); 27642d1d418eSSumit Saxena if (retval) { 27652d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_ERROR, 27662d1d418eSSumit Saxena "%s :Failed to soft reset IOC, error 0x%d\n", 27672d1d418eSSumit Saxena __func__, retval); 27682d1d418eSSumit Saxena goto out_failed; 27692d1d418eSSumit Saxena } 27702d1d418eSSumit Saxena } 27712d1d418eSSumit Saxena 27722d1d418eSSumit Saxena ioc_state = mpi3mr_get_iocstate(sc); 27732d1d418eSSumit Saxena 27742d1d418eSSumit Saxena if (ioc_state != MRIOC_STATE_RESET) { 27752d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_ERROR, "Cannot bring IOC to reset state\n"); 27762d1d418eSSumit Saxena goto out_failed; 27772d1d418eSSumit Saxena } 27782d1d418eSSumit Saxena 27792d1d418eSSumit Saxena retval = mpi3mr_setup_admin_qpair(sc); 27802d1d418eSSumit Saxena if (retval) { 27812d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_ERROR, "Failed to setup Admin queues, error 0x%x\n", 27822d1d418eSSumit Saxena retval); 27832d1d418eSSumit Saxena goto out_failed; 27842d1d418eSSumit Saxena } 27852d1d418eSSumit Saxena 27862d1d418eSSumit Saxena retval = mpi3mr_bring_ioc_ready(sc); 27872d1d418eSSumit Saxena if (retval) { 27882d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_ERROR, "Failed to bring IOC ready, error 0x%x\n", 27892d1d418eSSumit Saxena retval); 27902d1d418eSSumit Saxena goto out_failed; 27912d1d418eSSumit Saxena } 27922d1d418eSSumit Saxena 27932d1d418eSSumit Saxena if (init_type == MPI3MR_INIT_TYPE_INIT) { 27942d1d418eSSumit Saxena retval = mpi3mr_alloc_interrupts(sc, 1); 27952d1d418eSSumit Saxena if (retval) { 27962d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_ERROR, "Failed to allocate interrupts, error 0x%x\n", 27972d1d418eSSumit Saxena retval); 27982d1d418eSSumit Saxena goto out_failed; 27992d1d418eSSumit Saxena } 28002d1d418eSSumit Saxena 28012d1d418eSSumit Saxena retval = mpi3mr_setup_irqs(sc); 28022d1d418eSSumit Saxena if (retval) { 28032d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_ERROR, "Failed to setup ISR, error 0x%x\n", 28042d1d418eSSumit Saxena retval); 28052d1d418eSSumit Saxena goto out_failed; 28062d1d418eSSumit Saxena } 28072d1d418eSSumit Saxena } 28082d1d418eSSumit Saxena 28092d1d418eSSumit Saxena mpi3mr_enable_interrupts(sc); 28102d1d418eSSumit Saxena 28112d1d418eSSumit Saxena if (init_type == MPI3MR_INIT_TYPE_INIT) { 28122d1d418eSSumit Saxena mtx_init(&sc->mpi3mr_mtx, "SIM lock", NULL, MTX_DEF); 28132d1d418eSSumit Saxena mtx_init(&sc->io_lock, "IO lock", NULL, MTX_DEF); 28142d1d418eSSumit Saxena mtx_init(&sc->admin_req_lock, "Admin Request Queue lock", NULL, MTX_SPIN); 28152d1d418eSSumit Saxena mtx_init(&sc->reply_free_q_lock, "Reply free Queue lock", NULL, MTX_SPIN); 28162d1d418eSSumit Saxena mtx_init(&sc->sense_buf_q_lock, "Sense buffer Queue lock", NULL, MTX_SPIN); 28172d1d418eSSumit Saxena mtx_init(&sc->chain_buf_lock, "Chain buffer lock", NULL, MTX_SPIN); 28182d1d418eSSumit Saxena mtx_init(&sc->cmd_pool_lock, "Command pool lock", NULL, MTX_DEF); 28192d1d418eSSumit Saxena mtx_init(&sc->fwevt_lock, "Firmware Event lock", NULL, MTX_DEF); 28202d1d418eSSumit Saxena mtx_init(&sc->target_lock, "Target lock", NULL, MTX_SPIN); 28212d1d418eSSumit Saxena mtx_init(&sc->reset_mutex, "Reset lock", NULL, MTX_DEF); 28222d1d418eSSumit Saxena 28232d1d418eSSumit Saxena mtx_init(&sc->init_cmds.completion.lock, "Init commands lock", NULL, MTX_DEF); 28242d1d418eSSumit Saxena sc->init_cmds.reply = NULL; 28252d1d418eSSumit Saxena sc->init_cmds.state = MPI3MR_CMD_NOTUSED; 28262d1d418eSSumit Saxena sc->init_cmds.dev_handle = MPI3MR_INVALID_DEV_HANDLE; 28272d1d418eSSumit Saxena sc->init_cmds.host_tag = MPI3MR_HOSTTAG_INITCMDS; 28282d1d418eSSumit Saxena 28292d1d418eSSumit Saxena mtx_init(&sc->ioctl_cmds.completion.lock, "IOCTL commands lock", NULL, MTX_DEF); 28302d1d418eSSumit Saxena sc->ioctl_cmds.reply = NULL; 28312d1d418eSSumit Saxena sc->ioctl_cmds.state = MPI3MR_CMD_NOTUSED; 28322d1d418eSSumit Saxena sc->ioctl_cmds.dev_handle = MPI3MR_INVALID_DEV_HANDLE; 28332d1d418eSSumit Saxena sc->ioctl_cmds.host_tag = MPI3MR_HOSTTAG_IOCTLCMDS; 28342d1d418eSSumit Saxena 28352d1d418eSSumit Saxena mtx_init(&sc->pel_abort_cmd.completion.lock, "PEL Abort command lock", NULL, MTX_DEF); 28362d1d418eSSumit Saxena sc->pel_abort_cmd.reply = NULL; 28372d1d418eSSumit Saxena sc->pel_abort_cmd.state = MPI3MR_CMD_NOTUSED; 28382d1d418eSSumit Saxena sc->pel_abort_cmd.dev_handle = MPI3MR_INVALID_DEV_HANDLE; 28392d1d418eSSumit Saxena sc->pel_abort_cmd.host_tag = MPI3MR_HOSTTAG_PELABORT; 28402d1d418eSSumit Saxena 28412d1d418eSSumit Saxena mtx_init(&sc->host_tm_cmds.completion.lock, "TM commands lock", NULL, MTX_DEF); 28422d1d418eSSumit Saxena sc->host_tm_cmds.reply = NULL; 28432d1d418eSSumit Saxena sc->host_tm_cmds.state = MPI3MR_CMD_NOTUSED; 28442d1d418eSSumit Saxena sc->host_tm_cmds.dev_handle = MPI3MR_INVALID_DEV_HANDLE; 28452d1d418eSSumit Saxena sc->host_tm_cmds.host_tag = MPI3MR_HOSTTAG_TMS; 28462d1d418eSSumit Saxena 28472d1d418eSSumit Saxena TAILQ_INIT(&sc->cmd_list_head); 28482d1d418eSSumit Saxena TAILQ_INIT(&sc->event_list); 28492d1d418eSSumit Saxena TAILQ_INIT(&sc->delayed_rmhs_list); 28502d1d418eSSumit Saxena TAILQ_INIT(&sc->delayed_evtack_cmds_list); 28512d1d418eSSumit Saxena 28522d1d418eSSumit Saxena for (i = 0; i < MPI3MR_NUM_DEVRMCMD; i++) { 28532d1d418eSSumit Saxena snprintf(str, 32, "Dev REMHS commands lock[%d]", i); 28542d1d418eSSumit Saxena mtx_init(&sc->dev_rmhs_cmds[i].completion.lock, str, NULL, MTX_DEF); 28552d1d418eSSumit Saxena sc->dev_rmhs_cmds[i].reply = NULL; 28562d1d418eSSumit Saxena sc->dev_rmhs_cmds[i].state = MPI3MR_CMD_NOTUSED; 28572d1d418eSSumit Saxena sc->dev_rmhs_cmds[i].dev_handle = MPI3MR_INVALID_DEV_HANDLE; 28582d1d418eSSumit Saxena sc->dev_rmhs_cmds[i].host_tag = MPI3MR_HOSTTAG_DEVRMCMD_MIN 28592d1d418eSSumit Saxena + i; 28602d1d418eSSumit Saxena } 28612d1d418eSSumit Saxena } 28622d1d418eSSumit Saxena 28632d1d418eSSumit Saxena retval = mpi3mr_issue_iocfacts(sc, &facts_data); 28642d1d418eSSumit Saxena if (retval) { 28652d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_ERROR, "Failed to Issue IOC Facts, retval: 0x%x\n", 28662d1d418eSSumit Saxena retval); 28672d1d418eSSumit Saxena goto out_failed; 28682d1d418eSSumit Saxena } 28692d1d418eSSumit Saxena 28702d1d418eSSumit Saxena retval = mpi3mr_process_factsdata(sc, &facts_data); 28712d1d418eSSumit Saxena if (retval) { 28722d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_ERROR, "IOC Facts data processing failedi, retval: 0x%x\n", 28732d1d418eSSumit Saxena retval); 28742d1d418eSSumit Saxena goto out_failed; 28752d1d418eSSumit Saxena } 28762d1d418eSSumit Saxena 28772d1d418eSSumit Saxena sc->num_io_throttle_group = sc->facts.max_io_throttle_group; 28782d1d418eSSumit Saxena mpi3mr_atomic_set(&sc->pend_large_data_sz, 0); 28792d1d418eSSumit Saxena 28802d1d418eSSumit Saxena if (init_type == MPI3MR_INIT_TYPE_RESET) { 28812d1d418eSSumit Saxena retval = mpi3mr_validate_fw_update(sc); 28822d1d418eSSumit Saxena if (retval) 28832d1d418eSSumit Saxena goto out_failed; 28842d1d418eSSumit Saxena } else { 28852d1d418eSSumit Saxena sc->reply_sz = sc->facts.reply_sz; 28862d1d418eSSumit Saxena } 28872d1d418eSSumit Saxena 28882d1d418eSSumit Saxena mpi3mr_display_ioc_info(sc); 28892d1d418eSSumit Saxena 28902d1d418eSSumit Saxena retval = mpi3mr_reply_alloc(sc); 28912d1d418eSSumit Saxena if (retval) { 28922d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_ERROR, "Failed to allocated reply and sense buffers, retval: 0x%x\n", 28932d1d418eSSumit Saxena retval); 28942d1d418eSSumit Saxena goto out_failed; 28952d1d418eSSumit Saxena } 28962d1d418eSSumit Saxena 28972d1d418eSSumit Saxena if (init_type == MPI3MR_INIT_TYPE_INIT) { 28982d1d418eSSumit Saxena retval = mpi3mr_alloc_chain_bufs(sc); 28992d1d418eSSumit Saxena if (retval) { 29002d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_ERROR, "Failed to allocated chain buffers, retval: 0x%x\n", 29012d1d418eSSumit Saxena retval); 29022d1d418eSSumit Saxena goto out_failed; 29032d1d418eSSumit Saxena } 29042d1d418eSSumit Saxena } 29052d1d418eSSumit Saxena 29062d1d418eSSumit Saxena retval = mpi3mr_issue_iocinit(sc); 29072d1d418eSSumit Saxena if (retval) { 29082d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_ERROR, "Failed to Issue IOC Init, retval: 0x%x\n", 29092d1d418eSSumit Saxena retval); 29102d1d418eSSumit Saxena goto out_failed; 29112d1d418eSSumit Saxena } 29122d1d418eSSumit Saxena 29132d1d418eSSumit Saxena mpi3mr_print_fw_pkg_ver(sc); 29142d1d418eSSumit Saxena 29152d1d418eSSumit Saxena sc->reply_free_q_host_index = sc->num_reply_bufs; 29162d1d418eSSumit Saxena mpi3mr_regwrite(sc, MPI3_SYSIF_REPLY_FREE_HOST_INDEX_OFFSET, 29172d1d418eSSumit Saxena sc->reply_free_q_host_index); 29182d1d418eSSumit Saxena 29192d1d418eSSumit Saxena sc->sense_buf_q_host_index = sc->num_sense_bufs; 29202d1d418eSSumit Saxena 29212d1d418eSSumit Saxena mpi3mr_regwrite(sc, MPI3_SYSIF_SENSE_BUF_FREE_HOST_INDEX_OFFSET, 29222d1d418eSSumit Saxena sc->sense_buf_q_host_index); 29232d1d418eSSumit Saxena 29242d1d418eSSumit Saxena if (init_type == MPI3MR_INIT_TYPE_INIT) { 29252d1d418eSSumit Saxena retval = mpi3mr_alloc_interrupts(sc, 0); 29262d1d418eSSumit Saxena if (retval) { 29272d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_ERROR, "Failed to allocate interrupts, retval: 0x%x\n", 29282d1d418eSSumit Saxena retval); 29292d1d418eSSumit Saxena goto out_failed; 29302d1d418eSSumit Saxena } 29312d1d418eSSumit Saxena 29322d1d418eSSumit Saxena retval = mpi3mr_setup_irqs(sc); 29332d1d418eSSumit Saxena if (retval) { 29342d1d418eSSumit Saxena printf(IOCNAME "Failed to setup ISR, error: 0x%x\n", 29352d1d418eSSumit Saxena sc->name, retval); 29362d1d418eSSumit Saxena goto out_failed; 29372d1d418eSSumit Saxena } 29382d1d418eSSumit Saxena 29392d1d418eSSumit Saxena mpi3mr_enable_interrupts(sc); 29402d1d418eSSumit Saxena 29412d1d418eSSumit Saxena } else 29422d1d418eSSumit Saxena mpi3mr_enable_interrupts(sc); 29432d1d418eSSumit Saxena 29442d1d418eSSumit Saxena retval = mpi3mr_create_op_queues(sc); 29452d1d418eSSumit Saxena 29462d1d418eSSumit Saxena if (retval) { 29472d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_ERROR, "Failed to create operational queues, error: %d\n", 29482d1d418eSSumit Saxena retval); 29492d1d418eSSumit Saxena goto out_failed; 29502d1d418eSSumit Saxena } 29512d1d418eSSumit Saxena 29522d1d418eSSumit Saxena if (!sc->throttle_groups && sc->num_io_throttle_group) { 29532d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_ERROR, "allocating memory for throttle groups\n"); 29542d1d418eSSumit Saxena size = sizeof(struct mpi3mr_throttle_group_info); 29552d1d418eSSumit Saxena sc->throttle_groups = (struct mpi3mr_throttle_group_info *) 29562d1d418eSSumit Saxena malloc(sc->num_io_throttle_group * 29572d1d418eSSumit Saxena size, M_MPI3MR, M_NOWAIT | M_ZERO); 29582d1d418eSSumit Saxena if (!sc->throttle_groups) 29592d1d418eSSumit Saxena goto out_failed; 29602d1d418eSSumit Saxena } 29612d1d418eSSumit Saxena 29622d1d418eSSumit Saxena if (init_type == MPI3MR_INIT_TYPE_RESET) { 29632d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_INFO, "Re-register events\n"); 29642d1d418eSSumit Saxena retval = mpi3mr_register_events(sc); 29652d1d418eSSumit Saxena if (retval) { 29662d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_INFO, "Failed to re-register events, retval: 0x%x\n", 29672d1d418eSSumit Saxena retval); 29682d1d418eSSumit Saxena goto out_failed; 29692d1d418eSSumit Saxena } 29702d1d418eSSumit Saxena 29712d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_INFO, "Issuing Port Enable\n"); 29722d1d418eSSumit Saxena retval = mpi3mr_issue_port_enable(sc, 0); 29732d1d418eSSumit Saxena if (retval) { 29742d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_INFO, "Failed to issue port enable, retval: 0x%x\n", 29752d1d418eSSumit Saxena retval); 29762d1d418eSSumit Saxena goto out_failed; 29772d1d418eSSumit Saxena } 29782d1d418eSSumit Saxena } 29792d1d418eSSumit Saxena retval = mpi3mr_pel_alloc(sc); 29802d1d418eSSumit Saxena if (retval) { 29812d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_ERROR, "Failed to allocate memory for PEL, retval: 0x%x\n", 29822d1d418eSSumit Saxena retval); 29832d1d418eSSumit Saxena goto out_failed; 29842d1d418eSSumit Saxena } 29852d1d418eSSumit Saxena 29862d1d418eSSumit Saxena return retval; 29872d1d418eSSumit Saxena 29882d1d418eSSumit Saxena out_failed: 29892d1d418eSSumit Saxena retval = -1; 29902d1d418eSSumit Saxena return retval; 29912d1d418eSSumit Saxena } 29922d1d418eSSumit Saxena 29932d1d418eSSumit Saxena static void mpi3mr_port_enable_complete(struct mpi3mr_softc *sc, 29942d1d418eSSumit Saxena struct mpi3mr_drvr_cmd *drvrcmd) 29952d1d418eSSumit Saxena { 29962d1d418eSSumit Saxena drvrcmd->state = MPI3MR_CMD_NOTUSED; 29972d1d418eSSumit Saxena drvrcmd->callback = NULL; 29982d1d418eSSumit Saxena printf(IOCNAME "Completing Port Enable Request\n", sc->name); 29992d1d418eSSumit Saxena sc->mpi3mr_flags |= MPI3MR_FLAGS_PORT_ENABLE_DONE; 30002d1d418eSSumit Saxena mpi3mr_startup_decrement(sc->cam_sc); 30012d1d418eSSumit Saxena } 30022d1d418eSSumit Saxena 30032d1d418eSSumit Saxena int mpi3mr_issue_port_enable(struct mpi3mr_softc *sc, U8 async) 30042d1d418eSSumit Saxena { 30052d1d418eSSumit Saxena Mpi3PortEnableRequest_t pe_req; 30062d1d418eSSumit Saxena int retval = 0; 30072d1d418eSSumit Saxena 30082d1d418eSSumit Saxena memset(&pe_req, 0, sizeof(pe_req)); 30092d1d418eSSumit Saxena mtx_lock(&sc->init_cmds.completion.lock); 30102d1d418eSSumit Saxena if (sc->init_cmds.state & MPI3MR_CMD_PENDING) { 30112d1d418eSSumit Saxena retval = -1; 30122d1d418eSSumit Saxena printf(IOCNAME "Issue PortEnable: Init command is in use\n", sc->name); 30132d1d418eSSumit Saxena mtx_unlock(&sc->init_cmds.completion.lock); 30142d1d418eSSumit Saxena goto out; 30152d1d418eSSumit Saxena } 30162d1d418eSSumit Saxena 30172d1d418eSSumit Saxena sc->init_cmds.state = MPI3MR_CMD_PENDING; 30182d1d418eSSumit Saxena 30192d1d418eSSumit Saxena if (async) { 30202d1d418eSSumit Saxena sc->init_cmds.is_waiting = 0; 30212d1d418eSSumit Saxena sc->init_cmds.callback = mpi3mr_port_enable_complete; 30222d1d418eSSumit Saxena } else { 30232d1d418eSSumit Saxena sc->init_cmds.is_waiting = 1; 30242d1d418eSSumit Saxena sc->init_cmds.callback = NULL; 30252d1d418eSSumit Saxena init_completion(&sc->init_cmds.completion); 30262d1d418eSSumit Saxena } 30272d1d418eSSumit Saxena pe_req.HostTag = MPI3MR_HOSTTAG_INITCMDS; 30282d1d418eSSumit Saxena pe_req.Function = MPI3_FUNCTION_PORT_ENABLE; 30292d1d418eSSumit Saxena 30302d1d418eSSumit Saxena printf(IOCNAME "Sending Port Enable Request\n", sc->name); 30312d1d418eSSumit Saxena retval = mpi3mr_submit_admin_cmd(sc, &pe_req, sizeof(pe_req)); 30322d1d418eSSumit Saxena if (retval) { 30332d1d418eSSumit Saxena printf(IOCNAME "Issue PortEnable: Admin Post failed\n", 30342d1d418eSSumit Saxena sc->name); 30352d1d418eSSumit Saxena goto out_unlock; 30362d1d418eSSumit Saxena } 30372d1d418eSSumit Saxena 30382d1d418eSSumit Saxena if (!async) { 30392d1d418eSSumit Saxena wait_for_completion_timeout(&sc->init_cmds.completion, 30402d1d418eSSumit Saxena MPI3MR_PORTENABLE_TIMEOUT); 30412d1d418eSSumit Saxena if (!(sc->init_cmds.state & MPI3MR_CMD_COMPLETE)) { 30422d1d418eSSumit Saxena printf(IOCNAME "Issue PortEnable: command timed out\n", 30432d1d418eSSumit Saxena sc->name); 30442d1d418eSSumit Saxena retval = -1; 30452d1d418eSSumit Saxena mpi3mr_check_rh_fault_ioc(sc, MPI3MR_RESET_FROM_PE_TIMEOUT); 30462d1d418eSSumit Saxena goto out_unlock; 30472d1d418eSSumit Saxena } 30482d1d418eSSumit Saxena mpi3mr_port_enable_complete(sc, &sc->init_cmds); 30492d1d418eSSumit Saxena } 30502d1d418eSSumit Saxena out_unlock: 30512d1d418eSSumit Saxena mtx_unlock(&sc->init_cmds.completion.lock); 30522d1d418eSSumit Saxena 30532d1d418eSSumit Saxena out: 30542d1d418eSSumit Saxena return retval; 30552d1d418eSSumit Saxena } 30562d1d418eSSumit Saxena 30572d1d418eSSumit Saxena void 30582d1d418eSSumit Saxena mpi3mr_watchdog_thread(void *arg) 30592d1d418eSSumit Saxena { 30602d1d418eSSumit Saxena struct mpi3mr_softc *sc; 30612d1d418eSSumit Saxena enum mpi3mr_iocstate ioc_state; 30622d1d418eSSumit Saxena U32 fault, host_diagnostic, ioc_status; 30632d1d418eSSumit Saxena 30642d1d418eSSumit Saxena sc = (struct mpi3mr_softc *)arg; 30652d1d418eSSumit Saxena 30662d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_XINFO, "%s\n", __func__); 30672d1d418eSSumit Saxena 30682d1d418eSSumit Saxena sc->watchdog_thread_active = 1; 30692d1d418eSSumit Saxena mtx_lock(&sc->reset_mutex); 30702d1d418eSSumit Saxena for (;;) { 30712d1d418eSSumit Saxena if (sc->mpi3mr_flags & MPI3MR_FLAGS_SHUTDOWN || 30722d1d418eSSumit Saxena (sc->unrecoverable == 1)) { 30732d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_INFO, 30742d1d418eSSumit Saxena "Exit due to %s from %s\n", 30752d1d418eSSumit Saxena sc->mpi3mr_flags & MPI3MR_FLAGS_SHUTDOWN ? "Shutdown" : 30762d1d418eSSumit Saxena "Hardware critical error", __func__); 30772d1d418eSSumit Saxena break; 30782d1d418eSSumit Saxena } 30797c491309SWarner Losh mtx_unlock(&sc->reset_mutex); 30802d1d418eSSumit Saxena 30812d1d418eSSumit Saxena if ((sc->prepare_for_reset) && 30822d1d418eSSumit Saxena ((sc->prepare_for_reset_timeout_counter++) >= 30832d1d418eSSumit Saxena MPI3MR_PREPARE_FOR_RESET_TIMEOUT)) { 30842d1d418eSSumit Saxena mpi3mr_soft_reset_handler(sc, 30852d1d418eSSumit Saxena MPI3MR_RESET_FROM_CIACTVRST_TIMER, 1); 30867c491309SWarner Losh goto sleep; 30872d1d418eSSumit Saxena } 30882d1d418eSSumit Saxena 30892d1d418eSSumit Saxena ioc_status = mpi3mr_regread(sc, MPI3_SYSIF_IOC_STATUS_OFFSET); 30902d1d418eSSumit Saxena 30912d1d418eSSumit Saxena if (ioc_status & MPI3_SYSIF_IOC_STATUS_RESET_HISTORY) { 30922d1d418eSSumit Saxena mpi3mr_soft_reset_handler(sc, MPI3MR_RESET_FROM_FIRMWARE, 0); 30937c491309SWarner Losh goto sleep; 30942d1d418eSSumit Saxena } 30952d1d418eSSumit Saxena 30962d1d418eSSumit Saxena ioc_state = mpi3mr_get_iocstate(sc); 30972d1d418eSSumit Saxena if (ioc_state == MRIOC_STATE_FAULT) { 30982d1d418eSSumit Saxena fault = mpi3mr_regread(sc, MPI3_SYSIF_FAULT_OFFSET) & 30992d1d418eSSumit Saxena MPI3_SYSIF_FAULT_CODE_MASK; 31002d1d418eSSumit Saxena 31012d1d418eSSumit Saxena host_diagnostic = mpi3mr_regread(sc, MPI3_SYSIF_HOST_DIAG_OFFSET); 31022d1d418eSSumit Saxena if (host_diagnostic & MPI3_SYSIF_HOST_DIAG_SAVE_IN_PROGRESS) { 31032d1d418eSSumit Saxena if (!sc->diagsave_timeout) { 31042d1d418eSSumit Saxena mpi3mr_print_fault_info(sc); 31052d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_INFO, 31062d1d418eSSumit Saxena "diag save in progress\n"); 31072d1d418eSSumit Saxena } 31082d1d418eSSumit Saxena if ((sc->diagsave_timeout++) <= MPI3_SYSIF_DIAG_SAVE_TIMEOUT) 31097c491309SWarner Losh goto sleep; 31102d1d418eSSumit Saxena } 31112d1d418eSSumit Saxena mpi3mr_print_fault_info(sc); 31122d1d418eSSumit Saxena sc->diagsave_timeout = 0; 31132d1d418eSSumit Saxena 31142d1d418eSSumit Saxena if ((fault == MPI3_SYSIF_FAULT_CODE_POWER_CYCLE_REQUIRED) || 31152d1d418eSSumit Saxena (fault == MPI3_SYSIF_FAULT_CODE_COMPLETE_RESET_NEEDED)) { 31162d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_INFO, 31172d1d418eSSumit Saxena "Controller requires system power cycle or complete reset is needed," 31182d1d418eSSumit Saxena "fault code: 0x%x. marking controller as unrecoverable\n", fault); 31192d1d418eSSumit Saxena sc->unrecoverable = 1; 31207c491309SWarner Losh break; 31212d1d418eSSumit Saxena } 31222d1d418eSSumit Saxena if ((fault == MPI3_SYSIF_FAULT_CODE_DIAG_FAULT_RESET) 31232d1d418eSSumit Saxena || (fault == MPI3_SYSIF_FAULT_CODE_SOFT_RESET_IN_PROGRESS) 31242d1d418eSSumit Saxena || (sc->reset_in_progress)) 31257c491309SWarner Losh break; 31262d1d418eSSumit Saxena if (fault == MPI3_SYSIF_FAULT_CODE_CI_ACTIVATION_RESET) 31272d1d418eSSumit Saxena mpi3mr_soft_reset_handler(sc, 31282d1d418eSSumit Saxena MPI3MR_RESET_FROM_CIACTIV_FAULT, 0); 31292d1d418eSSumit Saxena else 31302d1d418eSSumit Saxena mpi3mr_soft_reset_handler(sc, 31312d1d418eSSumit Saxena MPI3MR_RESET_FROM_FAULT_WATCH, 0); 31322d1d418eSSumit Saxena 31332d1d418eSSumit Saxena } 31342d1d418eSSumit Saxena 31352d1d418eSSumit Saxena if (sc->reset.type == MPI3MR_TRIGGER_SOFT_RESET) { 31362d1d418eSSumit Saxena mpi3mr_print_fault_info(sc); 31372d1d418eSSumit Saxena mpi3mr_soft_reset_handler(sc, sc->reset.reason, 1); 31382d1d418eSSumit Saxena } 31397c491309SWarner Losh sleep: 31407c491309SWarner Losh mtx_lock(&sc->reset_mutex); 31417c491309SWarner Losh /* 31427c491309SWarner Losh * Sleep for 1 second if we're not exiting, then loop to top 31437c491309SWarner Losh * to poll exit status and hardware health. 31447c491309SWarner Losh */ 31457c491309SWarner Losh if ((sc->mpi3mr_flags & MPI3MR_FLAGS_SHUTDOWN) == 0 && 31467c491309SWarner Losh !sc->unrecoverable) { 31477c491309SWarner Losh msleep(&sc->watchdog_chan, &sc->reset_mutex, PRIBIO, 31487c491309SWarner Losh "mpi3mr_watchdog", 1 * hz); 31492d1d418eSSumit Saxena } 31507c491309SWarner Losh } 31512d1d418eSSumit Saxena mtx_unlock(&sc->reset_mutex); 31522d1d418eSSumit Saxena sc->watchdog_thread_active = 0; 31532d1d418eSSumit Saxena mpi3mr_kproc_exit(0); 31542d1d418eSSumit Saxena } 31552d1d418eSSumit Saxena 31562d1d418eSSumit Saxena static void mpi3mr_display_event_data(struct mpi3mr_softc *sc, 31572d1d418eSSumit Saxena Mpi3EventNotificationReply_t *event_rep) 31582d1d418eSSumit Saxena { 31592d1d418eSSumit Saxena char *desc = NULL; 31602d1d418eSSumit Saxena U16 event; 31612d1d418eSSumit Saxena 31622d1d418eSSumit Saxena event = event_rep->Event; 31632d1d418eSSumit Saxena 31642d1d418eSSumit Saxena switch (event) { 31652d1d418eSSumit Saxena case MPI3_EVENT_LOG_DATA: 31662d1d418eSSumit Saxena desc = "Log Data"; 31672d1d418eSSumit Saxena break; 31682d1d418eSSumit Saxena case MPI3_EVENT_CHANGE: 31692d1d418eSSumit Saxena desc = "Event Change"; 31702d1d418eSSumit Saxena break; 31712d1d418eSSumit Saxena case MPI3_EVENT_GPIO_INTERRUPT: 31722d1d418eSSumit Saxena desc = "GPIO Interrupt"; 31732d1d418eSSumit Saxena break; 31742d1d418eSSumit Saxena case MPI3_EVENT_CABLE_MGMT: 31752d1d418eSSumit Saxena desc = "Cable Management"; 31762d1d418eSSumit Saxena break; 31772d1d418eSSumit Saxena case MPI3_EVENT_ENERGY_PACK_CHANGE: 31782d1d418eSSumit Saxena desc = "Energy Pack Change"; 31792d1d418eSSumit Saxena break; 31802d1d418eSSumit Saxena case MPI3_EVENT_DEVICE_ADDED: 31812d1d418eSSumit Saxena { 31822d1d418eSSumit Saxena Mpi3DevicePage0_t *event_data = 31832d1d418eSSumit Saxena (Mpi3DevicePage0_t *)event_rep->EventData; 31842d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_EVENT, "Device Added: Dev=0x%04x Form=0x%x Perst id: 0x%x\n", 31852d1d418eSSumit Saxena event_data->DevHandle, event_data->DeviceForm, event_data->PersistentID); 31862d1d418eSSumit Saxena return; 31872d1d418eSSumit Saxena } 31882d1d418eSSumit Saxena case MPI3_EVENT_DEVICE_INFO_CHANGED: 31892d1d418eSSumit Saxena { 31902d1d418eSSumit Saxena Mpi3DevicePage0_t *event_data = 31912d1d418eSSumit Saxena (Mpi3DevicePage0_t *)event_rep->EventData; 31922d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_EVENT, "Device Info Changed: Dev=0x%04x Form=0x%x\n", 31932d1d418eSSumit Saxena event_data->DevHandle, event_data->DeviceForm); 31942d1d418eSSumit Saxena return; 31952d1d418eSSumit Saxena } 31962d1d418eSSumit Saxena case MPI3_EVENT_DEVICE_STATUS_CHANGE: 31972d1d418eSSumit Saxena { 31982d1d418eSSumit Saxena Mpi3EventDataDeviceStatusChange_t *event_data = 31992d1d418eSSumit Saxena (Mpi3EventDataDeviceStatusChange_t *)event_rep->EventData; 32002d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_EVENT, "Device Status Change: Dev=0x%04x RC=0x%x\n", 32012d1d418eSSumit Saxena event_data->DevHandle, event_data->ReasonCode); 32022d1d418eSSumit Saxena return; 32032d1d418eSSumit Saxena } 32042d1d418eSSumit Saxena case MPI3_EVENT_SAS_DISCOVERY: 32052d1d418eSSumit Saxena { 32062d1d418eSSumit Saxena Mpi3EventDataSasDiscovery_t *event_data = 32072d1d418eSSumit Saxena (Mpi3EventDataSasDiscovery_t *)event_rep->EventData; 32082d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_EVENT, "SAS Discovery: (%s)", 32092d1d418eSSumit Saxena (event_data->ReasonCode == MPI3_EVENT_SAS_DISC_RC_STARTED) ? 32102d1d418eSSumit Saxena "start" : "stop"); 32112d1d418eSSumit Saxena if (event_data->DiscoveryStatus && 32122d1d418eSSumit Saxena (sc->mpi3mr_debug & MPI3MR_EVENT)) { 32132d1d418eSSumit Saxena printf("discovery_status(0x%08x)", 32142d1d418eSSumit Saxena event_data->DiscoveryStatus); 32152d1d418eSSumit Saxena 32162d1d418eSSumit Saxena } 32172d1d418eSSumit Saxena 32182d1d418eSSumit Saxena if (sc->mpi3mr_debug & MPI3MR_EVENT) 32192d1d418eSSumit Saxena printf("\n"); 32202d1d418eSSumit Saxena return; 32212d1d418eSSumit Saxena } 32222d1d418eSSumit Saxena case MPI3_EVENT_SAS_BROADCAST_PRIMITIVE: 32232d1d418eSSumit Saxena desc = "SAS Broadcast Primitive"; 32242d1d418eSSumit Saxena break; 32252d1d418eSSumit Saxena case MPI3_EVENT_SAS_NOTIFY_PRIMITIVE: 32262d1d418eSSumit Saxena desc = "SAS Notify Primitive"; 32272d1d418eSSumit Saxena break; 32282d1d418eSSumit Saxena case MPI3_EVENT_SAS_INIT_DEVICE_STATUS_CHANGE: 32292d1d418eSSumit Saxena desc = "SAS Init Device Status Change"; 32302d1d418eSSumit Saxena break; 32312d1d418eSSumit Saxena case MPI3_EVENT_SAS_INIT_TABLE_OVERFLOW: 32322d1d418eSSumit Saxena desc = "SAS Init Table Overflow"; 32332d1d418eSSumit Saxena break; 32342d1d418eSSumit Saxena case MPI3_EVENT_SAS_TOPOLOGY_CHANGE_LIST: 32352d1d418eSSumit Saxena desc = "SAS Topology Change List"; 32362d1d418eSSumit Saxena break; 32372d1d418eSSumit Saxena case MPI3_EVENT_ENCL_DEVICE_STATUS_CHANGE: 32382d1d418eSSumit Saxena desc = "Enclosure Device Status Change"; 32392d1d418eSSumit Saxena break; 32402d1d418eSSumit Saxena case MPI3_EVENT_HARD_RESET_RECEIVED: 32412d1d418eSSumit Saxena desc = "Hard Reset Received"; 32422d1d418eSSumit Saxena break; 32432d1d418eSSumit Saxena case MPI3_EVENT_SAS_PHY_COUNTER: 32442d1d418eSSumit Saxena desc = "SAS PHY Counter"; 32452d1d418eSSumit Saxena break; 32462d1d418eSSumit Saxena case MPI3_EVENT_SAS_DEVICE_DISCOVERY_ERROR: 32472d1d418eSSumit Saxena desc = "SAS Device Discovery Error"; 32482d1d418eSSumit Saxena break; 32492d1d418eSSumit Saxena case MPI3_EVENT_PCIE_TOPOLOGY_CHANGE_LIST: 32502d1d418eSSumit Saxena desc = "PCIE Topology Change List"; 32512d1d418eSSumit Saxena break; 32522d1d418eSSumit Saxena case MPI3_EVENT_PCIE_ENUMERATION: 32532d1d418eSSumit Saxena { 32542d1d418eSSumit Saxena Mpi3EventDataPcieEnumeration_t *event_data = 32552d1d418eSSumit Saxena (Mpi3EventDataPcieEnumeration_t *)event_rep->EventData; 32562d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_EVENT, "PCIE Enumeration: (%s)", 32572d1d418eSSumit Saxena (event_data->ReasonCode == 32582d1d418eSSumit Saxena MPI3_EVENT_PCIE_ENUM_RC_STARTED) ? "start" : 32592d1d418eSSumit Saxena "stop"); 32602d1d418eSSumit Saxena if (event_data->EnumerationStatus) 32612d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_EVENT, "enumeration_status(0x%08x)", 32622d1d418eSSumit Saxena event_data->EnumerationStatus); 32632d1d418eSSumit Saxena if (sc->mpi3mr_debug & MPI3MR_EVENT) 32642d1d418eSSumit Saxena printf("\n"); 32652d1d418eSSumit Saxena return; 32662d1d418eSSumit Saxena } 32672d1d418eSSumit Saxena case MPI3_EVENT_PREPARE_FOR_RESET: 32682d1d418eSSumit Saxena desc = "Prepare For Reset"; 32692d1d418eSSumit Saxena break; 32702d1d418eSSumit Saxena } 32712d1d418eSSumit Saxena 32722d1d418eSSumit Saxena if (!desc) 32732d1d418eSSumit Saxena return; 32742d1d418eSSumit Saxena 32752d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_EVENT, "%s\n", desc); 32762d1d418eSSumit Saxena } 32772d1d418eSSumit Saxena 32782d1d418eSSumit Saxena struct mpi3mr_target * 32792d1d418eSSumit Saxena mpi3mr_find_target_by_per_id(struct mpi3mr_cam_softc *cam_sc, 32802d1d418eSSumit Saxena uint16_t per_id) 32812d1d418eSSumit Saxena { 32822d1d418eSSumit Saxena struct mpi3mr_target *target = NULL; 32832d1d418eSSumit Saxena 32842d1d418eSSumit Saxena mtx_lock_spin(&cam_sc->sc->target_lock); 32852d1d418eSSumit Saxena TAILQ_FOREACH(target, &cam_sc->tgt_list, tgt_next) { 32862d1d418eSSumit Saxena if (target->per_id == per_id) 32872d1d418eSSumit Saxena break; 32882d1d418eSSumit Saxena } 32892d1d418eSSumit Saxena 32902d1d418eSSumit Saxena mtx_unlock_spin(&cam_sc->sc->target_lock); 32912d1d418eSSumit Saxena return target; 32922d1d418eSSumit Saxena } 32932d1d418eSSumit Saxena 32942d1d418eSSumit Saxena struct mpi3mr_target * 32952d1d418eSSumit Saxena mpi3mr_find_target_by_dev_handle(struct mpi3mr_cam_softc *cam_sc, 32962d1d418eSSumit Saxena uint16_t handle) 32972d1d418eSSumit Saxena { 32982d1d418eSSumit Saxena struct mpi3mr_target *target = NULL; 32992d1d418eSSumit Saxena 33002d1d418eSSumit Saxena mtx_lock_spin(&cam_sc->sc->target_lock); 33012d1d418eSSumit Saxena TAILQ_FOREACH(target, &cam_sc->tgt_list, tgt_next) { 33022d1d418eSSumit Saxena if (target->dev_handle == handle) 33032d1d418eSSumit Saxena break; 33042d1d418eSSumit Saxena 33052d1d418eSSumit Saxena } 33062d1d418eSSumit Saxena mtx_unlock_spin(&cam_sc->sc->target_lock); 33072d1d418eSSumit Saxena return target; 33082d1d418eSSumit Saxena } 33092d1d418eSSumit Saxena 33102d1d418eSSumit Saxena void mpi3mr_update_device(struct mpi3mr_softc *sc, 33112d1d418eSSumit Saxena struct mpi3mr_target *tgtdev, Mpi3DevicePage0_t *dev_pg0, 33122d1d418eSSumit Saxena bool is_added) 33132d1d418eSSumit Saxena { 33142d1d418eSSumit Saxena U16 flags = 0; 33152d1d418eSSumit Saxena 33162d1d418eSSumit Saxena tgtdev->per_id = (dev_pg0->PersistentID); 33172d1d418eSSumit Saxena tgtdev->dev_handle = (dev_pg0->DevHandle); 33182d1d418eSSumit Saxena tgtdev->dev_type = dev_pg0->DeviceForm; 33192d1d418eSSumit Saxena tgtdev->encl_handle = (dev_pg0->EnclosureHandle); 33202d1d418eSSumit Saxena tgtdev->parent_handle = (dev_pg0->ParentDevHandle); 33212d1d418eSSumit Saxena tgtdev->slot = (dev_pg0->Slot); 33222d1d418eSSumit Saxena tgtdev->qdepth = (dev_pg0->QueueDepth); 33232d1d418eSSumit Saxena tgtdev->wwid = (dev_pg0->WWID); 33242d1d418eSSumit Saxena 33252d1d418eSSumit Saxena flags = (dev_pg0->Flags); 33262d1d418eSSumit Saxena tgtdev->is_hidden = (flags & MPI3_DEVICE0_FLAGS_HIDDEN); 33272d1d418eSSumit Saxena if (is_added == true) 33282d1d418eSSumit Saxena tgtdev->io_throttle_enabled = 33292d1d418eSSumit Saxena (flags & MPI3_DEVICE0_FLAGS_IO_THROTTLING_REQUIRED) ? 1 : 0; 33302d1d418eSSumit Saxena 33312d1d418eSSumit Saxena switch (dev_pg0->AccessStatus) { 33322d1d418eSSumit Saxena case MPI3_DEVICE0_ASTATUS_NO_ERRORS: 33332d1d418eSSumit Saxena case MPI3_DEVICE0_ASTATUS_PREPARE: 33342d1d418eSSumit Saxena case MPI3_DEVICE0_ASTATUS_NEEDS_INITIALIZATION: 33352d1d418eSSumit Saxena case MPI3_DEVICE0_ASTATUS_DEVICE_MISSING_DELAY: 33362d1d418eSSumit Saxena break; 33372d1d418eSSumit Saxena default: 33382d1d418eSSumit Saxena tgtdev->is_hidden = 1; 33392d1d418eSSumit Saxena break; 33402d1d418eSSumit Saxena } 33412d1d418eSSumit Saxena 33422d1d418eSSumit Saxena switch (tgtdev->dev_type) { 33432d1d418eSSumit Saxena case MPI3_DEVICE_DEVFORM_SAS_SATA: 33442d1d418eSSumit Saxena { 33452d1d418eSSumit Saxena Mpi3Device0SasSataFormat_t *sasinf = 33462d1d418eSSumit Saxena &dev_pg0->DeviceSpecific.SasSataFormat; 33472d1d418eSSumit Saxena U16 dev_info = (sasinf->DeviceInfo); 33482d1d418eSSumit Saxena tgtdev->dev_spec.sassata_inf.dev_info = dev_info; 33492d1d418eSSumit Saxena tgtdev->dev_spec.sassata_inf.sas_address = 33502d1d418eSSumit Saxena (sasinf->SASAddress); 33512d1d418eSSumit Saxena if ((dev_info & MPI3_SAS_DEVICE_INFO_DEVICE_TYPE_MASK) != 33522d1d418eSSumit Saxena MPI3_SAS_DEVICE_INFO_DEVICE_TYPE_END_DEVICE) 33532d1d418eSSumit Saxena tgtdev->is_hidden = 1; 33542d1d418eSSumit Saxena else if (!(dev_info & (MPI3_SAS_DEVICE_INFO_STP_SATA_TARGET | 33552d1d418eSSumit Saxena MPI3_SAS_DEVICE_INFO_SSP_TARGET))) 33562d1d418eSSumit Saxena tgtdev->is_hidden = 1; 33572d1d418eSSumit Saxena break; 33582d1d418eSSumit Saxena } 33592d1d418eSSumit Saxena case MPI3_DEVICE_DEVFORM_PCIE: 33602d1d418eSSumit Saxena { 33612d1d418eSSumit Saxena Mpi3Device0PcieFormat_t *pcieinf = 33622d1d418eSSumit Saxena &dev_pg0->DeviceSpecific.PcieFormat; 33632d1d418eSSumit Saxena U16 dev_info = (pcieinf->DeviceInfo); 33642d1d418eSSumit Saxena 33652d1d418eSSumit Saxena tgtdev->q_depth = dev_pg0->QueueDepth; 33662d1d418eSSumit Saxena tgtdev->dev_spec.pcie_inf.dev_info = dev_info; 33672d1d418eSSumit Saxena tgtdev->dev_spec.pcie_inf.capb = 33682d1d418eSSumit Saxena (pcieinf->Capabilities); 33692d1d418eSSumit Saxena tgtdev->dev_spec.pcie_inf.mdts = MPI3MR_DEFAULT_MDTS; 33702d1d418eSSumit Saxena if (dev_pg0->AccessStatus == MPI3_DEVICE0_ASTATUS_NO_ERRORS) { 33712d1d418eSSumit Saxena tgtdev->dev_spec.pcie_inf.mdts = 33722d1d418eSSumit Saxena (pcieinf->MaximumDataTransferSize); 33732d1d418eSSumit Saxena tgtdev->dev_spec.pcie_inf.pgsz = pcieinf->PageSize; 33742d1d418eSSumit Saxena tgtdev->dev_spec.pcie_inf.reset_to = 33752d1d418eSSumit Saxena pcieinf->ControllerResetTO; 33762d1d418eSSumit Saxena tgtdev->dev_spec.pcie_inf.abort_to = 33772d1d418eSSumit Saxena pcieinf->NVMeAbortTO; 33782d1d418eSSumit Saxena } 33792d1d418eSSumit Saxena if (tgtdev->dev_spec.pcie_inf.mdts > (1024 * 1024)) 33802d1d418eSSumit Saxena tgtdev->dev_spec.pcie_inf.mdts = (1024 * 1024); 33812d1d418eSSumit Saxena 33822d1d418eSSumit Saxena if (((dev_info & MPI3_DEVICE0_PCIE_DEVICE_INFO_TYPE_MASK) != 33832d1d418eSSumit Saxena MPI3_DEVICE0_PCIE_DEVICE_INFO_TYPE_NVME_DEVICE) && 33842d1d418eSSumit Saxena ((dev_info & MPI3_DEVICE0_PCIE_DEVICE_INFO_TYPE_MASK) != 33852d1d418eSSumit Saxena MPI3_DEVICE0_PCIE_DEVICE_INFO_TYPE_SCSI_DEVICE)) 33862d1d418eSSumit Saxena tgtdev->is_hidden = 1; 33872d1d418eSSumit Saxena 33882d1d418eSSumit Saxena break; 33892d1d418eSSumit Saxena } 33902d1d418eSSumit Saxena case MPI3_DEVICE_DEVFORM_VD: 33912d1d418eSSumit Saxena { 33922d1d418eSSumit Saxena Mpi3Device0VdFormat_t *vdinf = 33932d1d418eSSumit Saxena &dev_pg0->DeviceSpecific.VdFormat; 33942d1d418eSSumit Saxena struct mpi3mr_throttle_group_info *tg = NULL; 33952d1d418eSSumit Saxena 33962d1d418eSSumit Saxena tgtdev->dev_spec.vol_inf.state = vdinf->VdState; 33972d1d418eSSumit Saxena if (vdinf->VdState == MPI3_DEVICE0_VD_STATE_OFFLINE) 33982d1d418eSSumit Saxena tgtdev->is_hidden = 1; 33992d1d418eSSumit Saxena tgtdev->dev_spec.vol_inf.tg_id = vdinf->IOThrottleGroup; 34002d1d418eSSumit Saxena tgtdev->dev_spec.vol_inf.tg_high = 34012d1d418eSSumit Saxena vdinf->IOThrottleGroupHigh * 2048; 34022d1d418eSSumit Saxena tgtdev->dev_spec.vol_inf.tg_low = 34032d1d418eSSumit Saxena vdinf->IOThrottleGroupLow * 2048; 34042d1d418eSSumit Saxena if (vdinf->IOThrottleGroup < sc->num_io_throttle_group) { 34052d1d418eSSumit Saxena tg = sc->throttle_groups + vdinf->IOThrottleGroup; 34062d1d418eSSumit Saxena tg->id = vdinf->IOThrottleGroup; 34072d1d418eSSumit Saxena tg->high = tgtdev->dev_spec.vol_inf.tg_high; 34082d1d418eSSumit Saxena tg->low = tgtdev->dev_spec.vol_inf.tg_low; 34092d1d418eSSumit Saxena if (is_added == true) 34102d1d418eSSumit Saxena tg->fw_qd = tgtdev->q_depth; 34112d1d418eSSumit Saxena tg->modified_qd = tgtdev->q_depth; 34122d1d418eSSumit Saxena } 34132d1d418eSSumit Saxena tgtdev->dev_spec.vol_inf.tg = tg; 34142d1d418eSSumit Saxena tgtdev->throttle_group = tg; 34152d1d418eSSumit Saxena break; 34162d1d418eSSumit Saxena } 34172d1d418eSSumit Saxena default: 34182d1d418eSSumit Saxena goto out; 34192d1d418eSSumit Saxena } 34202d1d418eSSumit Saxena 34212d1d418eSSumit Saxena out: 34222d1d418eSSumit Saxena return; 34232d1d418eSSumit Saxena } 34242d1d418eSSumit Saxena 34252d1d418eSSumit Saxena int mpi3mr_create_device(struct mpi3mr_softc *sc, 34262d1d418eSSumit Saxena Mpi3DevicePage0_t *dev_pg0) 34272d1d418eSSumit Saxena { 34282d1d418eSSumit Saxena int retval = 0; 34292d1d418eSSumit Saxena struct mpi3mr_target *target = NULL; 34302d1d418eSSumit Saxena U16 per_id = 0; 34312d1d418eSSumit Saxena 34322d1d418eSSumit Saxena per_id = dev_pg0->PersistentID; 34332d1d418eSSumit Saxena 34342d1d418eSSumit Saxena mtx_lock_spin(&sc->target_lock); 34352d1d418eSSumit Saxena TAILQ_FOREACH(target, &sc->cam_sc->tgt_list, tgt_next) { 34362d1d418eSSumit Saxena if (target->per_id == per_id) { 34372d1d418eSSumit Saxena target->state = MPI3MR_DEV_CREATED; 34382d1d418eSSumit Saxena break; 34392d1d418eSSumit Saxena } 34402d1d418eSSumit Saxena } 34412d1d418eSSumit Saxena mtx_unlock_spin(&sc->target_lock); 34422d1d418eSSumit Saxena 34432d1d418eSSumit Saxena if (target) { 34442d1d418eSSumit Saxena mpi3mr_update_device(sc, target, dev_pg0, true); 34452d1d418eSSumit Saxena } else { 34462d1d418eSSumit Saxena target = malloc(sizeof(*target), M_MPI3MR, 34472d1d418eSSumit Saxena M_NOWAIT | M_ZERO); 34482d1d418eSSumit Saxena 34492d1d418eSSumit Saxena if (target == NULL) { 34502d1d418eSSumit Saxena retval = -1; 34512d1d418eSSumit Saxena goto out; 34522d1d418eSSumit Saxena } 34532d1d418eSSumit Saxena 34542d1d418eSSumit Saxena target->exposed_to_os = 0; 34552d1d418eSSumit Saxena mpi3mr_update_device(sc, target, dev_pg0, true); 34562d1d418eSSumit Saxena mtx_lock_spin(&sc->target_lock); 34572d1d418eSSumit Saxena TAILQ_INSERT_TAIL(&sc->cam_sc->tgt_list, target, tgt_next); 34582d1d418eSSumit Saxena target->state = MPI3MR_DEV_CREATED; 34592d1d418eSSumit Saxena mtx_unlock_spin(&sc->target_lock); 34602d1d418eSSumit Saxena } 34612d1d418eSSumit Saxena out: 34622d1d418eSSumit Saxena return retval; 34632d1d418eSSumit Saxena } 34642d1d418eSSumit Saxena 34652d1d418eSSumit Saxena /** 34662d1d418eSSumit Saxena * mpi3mr_dev_rmhs_complete_iou - Device removal IOUC completion 34672d1d418eSSumit Saxena * @sc: Adapter instance reference 34682d1d418eSSumit Saxena * @drv_cmd: Internal command tracker 34692d1d418eSSumit Saxena * 34702d1d418eSSumit Saxena * Issues a target reset TM to the firmware from the device 34712d1d418eSSumit Saxena * removal TM pend list or retry the removal handshake sequence 34722d1d418eSSumit Saxena * based on the IOU control request IOC status. 34732d1d418eSSumit Saxena * 34742d1d418eSSumit Saxena * Return: Nothing 34752d1d418eSSumit Saxena */ 34762d1d418eSSumit Saxena static void mpi3mr_dev_rmhs_complete_iou(struct mpi3mr_softc *sc, 34772d1d418eSSumit Saxena struct mpi3mr_drvr_cmd *drv_cmd) 34782d1d418eSSumit Saxena { 34792d1d418eSSumit Saxena U16 cmd_idx = drv_cmd->host_tag - MPI3MR_HOSTTAG_DEVRMCMD_MIN; 34802d1d418eSSumit Saxena struct delayed_dev_rmhs_node *delayed_dev_rmhs = NULL; 3481701d776cSChandrakanth patil struct mpi3mr_target *tgtdev = NULL; 34822d1d418eSSumit Saxena 34832d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_EVENT, 34842d1d418eSSumit Saxena "%s :dev_rmhs_iouctrl_complete:handle(0x%04x), ioc_status(0x%04x), loginfo(0x%08x)\n", 34852d1d418eSSumit Saxena __func__, drv_cmd->dev_handle, drv_cmd->ioc_status, 34862d1d418eSSumit Saxena drv_cmd->ioc_loginfo); 34872d1d418eSSumit Saxena if (drv_cmd->ioc_status != MPI3_IOCSTATUS_SUCCESS) { 34882d1d418eSSumit Saxena if (drv_cmd->retry_count < MPI3MR_DEVRMHS_RETRYCOUNT) { 34892d1d418eSSumit Saxena drv_cmd->retry_count++; 34902d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_EVENT, 34912d1d418eSSumit Saxena "%s :dev_rmhs_iouctrl_complete: handle(0x%04x)retrying handshake retry=%d\n", 34922d1d418eSSumit Saxena __func__, drv_cmd->dev_handle, 34932d1d418eSSumit Saxena drv_cmd->retry_count); 34942d1d418eSSumit Saxena mpi3mr_dev_rmhs_send_tm(sc, drv_cmd->dev_handle, 34952d1d418eSSumit Saxena drv_cmd, drv_cmd->iou_rc); 34962d1d418eSSumit Saxena return; 34972d1d418eSSumit Saxena } 34982d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_ERROR, 34992d1d418eSSumit Saxena "%s :dev removal handshake failed after all retries: handle(0x%04x)\n", 35002d1d418eSSumit Saxena __func__, drv_cmd->dev_handle); 35012d1d418eSSumit Saxena } else { 3502701d776cSChandrakanth patil mtx_lock_spin(&sc->target_lock); 3503701d776cSChandrakanth patil TAILQ_FOREACH(tgtdev, &sc->cam_sc->tgt_list, tgt_next) { 3504701d776cSChandrakanth patil if (tgtdev->dev_handle == drv_cmd->dev_handle) 3505701d776cSChandrakanth patil tgtdev->state = MPI3MR_DEV_REMOVE_HS_COMPLETED; 3506701d776cSChandrakanth patil } 3507701d776cSChandrakanth patil mtx_unlock_spin(&sc->target_lock); 3508701d776cSChandrakanth patil 35092d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_INFO, 35102d1d418eSSumit Saxena "%s :dev removal handshake completed successfully: handle(0x%04x)\n", 35112d1d418eSSumit Saxena __func__, drv_cmd->dev_handle); 35122d1d418eSSumit Saxena mpi3mr_clear_bit(drv_cmd->dev_handle, sc->removepend_bitmap); 35132d1d418eSSumit Saxena } 35142d1d418eSSumit Saxena 35152d1d418eSSumit Saxena if (!TAILQ_EMPTY(&sc->delayed_rmhs_list)) { 35162d1d418eSSumit Saxena delayed_dev_rmhs = TAILQ_FIRST(&sc->delayed_rmhs_list); 35172d1d418eSSumit Saxena drv_cmd->dev_handle = delayed_dev_rmhs->handle; 35182d1d418eSSumit Saxena drv_cmd->retry_count = 0; 35192d1d418eSSumit Saxena drv_cmd->iou_rc = delayed_dev_rmhs->iou_rc; 35202d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_EVENT, 35212d1d418eSSumit Saxena "%s :dev_rmhs_iouctrl_complete: processing delayed TM: handle(0x%04x)\n", 35222d1d418eSSumit Saxena __func__, drv_cmd->dev_handle); 35232d1d418eSSumit Saxena mpi3mr_dev_rmhs_send_tm(sc, drv_cmd->dev_handle, drv_cmd, 35242d1d418eSSumit Saxena drv_cmd->iou_rc); 35252d1d418eSSumit Saxena TAILQ_REMOVE(&sc->delayed_rmhs_list, delayed_dev_rmhs, list); 35262d1d418eSSumit Saxena free(delayed_dev_rmhs, M_MPI3MR); 35272d1d418eSSumit Saxena return; 35282d1d418eSSumit Saxena } 35292d1d418eSSumit Saxena drv_cmd->state = MPI3MR_CMD_NOTUSED; 35302d1d418eSSumit Saxena drv_cmd->callback = NULL; 35312d1d418eSSumit Saxena drv_cmd->retry_count = 0; 35322d1d418eSSumit Saxena drv_cmd->dev_handle = MPI3MR_INVALID_DEV_HANDLE; 35332d1d418eSSumit Saxena mpi3mr_clear_bit(cmd_idx, sc->devrem_bitmap); 35342d1d418eSSumit Saxena } 35352d1d418eSSumit Saxena 35362d1d418eSSumit Saxena /** 35372d1d418eSSumit Saxena * mpi3mr_dev_rmhs_complete_tm - Device removal TM completion 35382d1d418eSSumit Saxena * @sc: Adapter instance reference 35392d1d418eSSumit Saxena * @drv_cmd: Internal command tracker 35402d1d418eSSumit Saxena * 35412d1d418eSSumit Saxena * Issues a target reset TM to the firmware from the device 35422d1d418eSSumit Saxena * removal TM pend list or issue IO Unit control request as 35432d1d418eSSumit Saxena * part of device removal or hidden acknowledgment handshake. 35442d1d418eSSumit Saxena * 35452d1d418eSSumit Saxena * Return: Nothing 35462d1d418eSSumit Saxena */ 35472d1d418eSSumit Saxena static void mpi3mr_dev_rmhs_complete_tm(struct mpi3mr_softc *sc, 35482d1d418eSSumit Saxena struct mpi3mr_drvr_cmd *drv_cmd) 35492d1d418eSSumit Saxena { 35502d1d418eSSumit Saxena Mpi3IoUnitControlRequest_t iou_ctrl; 35512d1d418eSSumit Saxena U16 cmd_idx = drv_cmd->host_tag - MPI3MR_HOSTTAG_DEVRMCMD_MIN; 35522d1d418eSSumit Saxena Mpi3SCSITaskMgmtReply_t *tm_reply = NULL; 35532d1d418eSSumit Saxena int retval; 35542d1d418eSSumit Saxena 35552d1d418eSSumit Saxena if (drv_cmd->state & MPI3MR_CMD_REPLYVALID) 35562d1d418eSSumit Saxena tm_reply = (Mpi3SCSITaskMgmtReply_t *)drv_cmd->reply; 35572d1d418eSSumit Saxena 35582d1d418eSSumit Saxena if (tm_reply) 35592d1d418eSSumit Saxena printf(IOCNAME 35602d1d418eSSumit Saxena "dev_rmhs_tr_complete:handle(0x%04x), ioc_status(0x%04x), loginfo(0x%08x), term_count(%d)\n", 35612d1d418eSSumit Saxena sc->name, drv_cmd->dev_handle, drv_cmd->ioc_status, 35622d1d418eSSumit Saxena drv_cmd->ioc_loginfo, 35632d1d418eSSumit Saxena le32toh(tm_reply->TerminationCount)); 35642d1d418eSSumit Saxena 35652d1d418eSSumit Saxena printf(IOCNAME "Issuing IOU CTL: handle(0x%04x) dev_rmhs idx(%d)\n", 35662d1d418eSSumit Saxena sc->name, drv_cmd->dev_handle, cmd_idx); 35672d1d418eSSumit Saxena 35682d1d418eSSumit Saxena memset(&iou_ctrl, 0, sizeof(iou_ctrl)); 35692d1d418eSSumit Saxena 35702d1d418eSSumit Saxena drv_cmd->state = MPI3MR_CMD_PENDING; 35712d1d418eSSumit Saxena drv_cmd->is_waiting = 0; 35722d1d418eSSumit Saxena drv_cmd->callback = mpi3mr_dev_rmhs_complete_iou; 35732d1d418eSSumit Saxena iou_ctrl.Operation = drv_cmd->iou_rc; 35742d1d418eSSumit Saxena iou_ctrl.Param16[0] = htole16(drv_cmd->dev_handle); 35752d1d418eSSumit Saxena iou_ctrl.HostTag = htole16(drv_cmd->host_tag); 35762d1d418eSSumit Saxena iou_ctrl.Function = MPI3_FUNCTION_IO_UNIT_CONTROL; 35772d1d418eSSumit Saxena 35782d1d418eSSumit Saxena retval = mpi3mr_submit_admin_cmd(sc, &iou_ctrl, sizeof(iou_ctrl)); 35792d1d418eSSumit Saxena if (retval) { 35802d1d418eSSumit Saxena printf(IOCNAME "Issue DevRmHsTMIOUCTL: Admin post failed\n", 35812d1d418eSSumit Saxena sc->name); 35822d1d418eSSumit Saxena goto out_failed; 35832d1d418eSSumit Saxena } 35842d1d418eSSumit Saxena 35852d1d418eSSumit Saxena return; 35862d1d418eSSumit Saxena out_failed: 35872d1d418eSSumit Saxena drv_cmd->state = MPI3MR_CMD_NOTUSED; 35882d1d418eSSumit Saxena drv_cmd->callback = NULL; 35892d1d418eSSumit Saxena drv_cmd->dev_handle = MPI3MR_INVALID_DEV_HANDLE; 35902d1d418eSSumit Saxena drv_cmd->retry_count = 0; 35912d1d418eSSumit Saxena mpi3mr_clear_bit(cmd_idx, sc->devrem_bitmap); 35922d1d418eSSumit Saxena } 35932d1d418eSSumit Saxena 35942d1d418eSSumit Saxena /** 35952d1d418eSSumit Saxena * mpi3mr_dev_rmhs_send_tm - Issue TM for device removal 35962d1d418eSSumit Saxena * @sc: Adapter instance reference 35972d1d418eSSumit Saxena * @handle: Device handle 35982d1d418eSSumit Saxena * @cmdparam: Internal command tracker 35992d1d418eSSumit Saxena * @iou_rc: IO Unit reason code 36002d1d418eSSumit Saxena * 36012d1d418eSSumit Saxena * Issues a target reset TM to the firmware or add it to a pend 36022d1d418eSSumit Saxena * list as part of device removal or hidden acknowledgment 36032d1d418eSSumit Saxena * handshake. 36042d1d418eSSumit Saxena * 36052d1d418eSSumit Saxena * Return: Nothing 36062d1d418eSSumit Saxena */ 36072d1d418eSSumit Saxena static void mpi3mr_dev_rmhs_send_tm(struct mpi3mr_softc *sc, U16 handle, 36082d1d418eSSumit Saxena struct mpi3mr_drvr_cmd *cmdparam, U8 iou_rc) 36092d1d418eSSumit Saxena { 36102d1d418eSSumit Saxena Mpi3SCSITaskMgmtRequest_t tm_req; 36112d1d418eSSumit Saxena int retval = 0; 36122d1d418eSSumit Saxena U16 cmd_idx = MPI3MR_NUM_DEVRMCMD; 36132d1d418eSSumit Saxena U8 retrycount = 5; 36142d1d418eSSumit Saxena struct mpi3mr_drvr_cmd *drv_cmd = cmdparam; 36152d1d418eSSumit Saxena struct delayed_dev_rmhs_node *delayed_dev_rmhs = NULL; 36162d1d418eSSumit Saxena 36172d1d418eSSumit Saxena if (drv_cmd) 36182d1d418eSSumit Saxena goto issue_cmd; 36192d1d418eSSumit Saxena do { 36202d1d418eSSumit Saxena cmd_idx = mpi3mr_find_first_zero_bit(sc->devrem_bitmap, 36212d1d418eSSumit Saxena MPI3MR_NUM_DEVRMCMD); 36222d1d418eSSumit Saxena if (cmd_idx < MPI3MR_NUM_DEVRMCMD) { 36232d1d418eSSumit Saxena if (!mpi3mr_test_and_set_bit(cmd_idx, sc->devrem_bitmap)) 36242d1d418eSSumit Saxena break; 36252d1d418eSSumit Saxena cmd_idx = MPI3MR_NUM_DEVRMCMD; 36262d1d418eSSumit Saxena } 36272d1d418eSSumit Saxena } while (retrycount--); 36282d1d418eSSumit Saxena 36292d1d418eSSumit Saxena if (cmd_idx >= MPI3MR_NUM_DEVRMCMD) { 36302d1d418eSSumit Saxena delayed_dev_rmhs = malloc(sizeof(*delayed_dev_rmhs),M_MPI3MR, 36312d1d418eSSumit Saxena M_ZERO|M_NOWAIT); 36322d1d418eSSumit Saxena 36332d1d418eSSumit Saxena if (!delayed_dev_rmhs) 36342d1d418eSSumit Saxena return; 36352d1d418eSSumit Saxena delayed_dev_rmhs->handle = handle; 36362d1d418eSSumit Saxena delayed_dev_rmhs->iou_rc = iou_rc; 36372d1d418eSSumit Saxena TAILQ_INSERT_TAIL(&(sc->delayed_rmhs_list), delayed_dev_rmhs, list); 36382d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_EVENT, "%s :DevRmHs: tr:handle(0x%04x) is postponed\n", 36392d1d418eSSumit Saxena __func__, handle); 36402d1d418eSSumit Saxena 36412d1d418eSSumit Saxena 36422d1d418eSSumit Saxena return; 36432d1d418eSSumit Saxena } 36442d1d418eSSumit Saxena drv_cmd = &sc->dev_rmhs_cmds[cmd_idx]; 36452d1d418eSSumit Saxena 36462d1d418eSSumit Saxena issue_cmd: 36472d1d418eSSumit Saxena cmd_idx = drv_cmd->host_tag - MPI3MR_HOSTTAG_DEVRMCMD_MIN; 36482d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_EVENT, 36492d1d418eSSumit Saxena "%s :Issuing TR TM: for devhandle 0x%04x with dev_rmhs %d\n", 36502d1d418eSSumit Saxena __func__, handle, cmd_idx); 36512d1d418eSSumit Saxena 36522d1d418eSSumit Saxena memset(&tm_req, 0, sizeof(tm_req)); 36532d1d418eSSumit Saxena if (drv_cmd->state & MPI3MR_CMD_PENDING) { 36542d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_EVENT, "%s :Issue TM: Command is in use\n", __func__); 36552d1d418eSSumit Saxena goto out; 36562d1d418eSSumit Saxena } 36572d1d418eSSumit Saxena drv_cmd->state = MPI3MR_CMD_PENDING; 36582d1d418eSSumit Saxena drv_cmd->is_waiting = 0; 36592d1d418eSSumit Saxena drv_cmd->callback = mpi3mr_dev_rmhs_complete_tm; 36602d1d418eSSumit Saxena drv_cmd->dev_handle = handle; 36612d1d418eSSumit Saxena drv_cmd->iou_rc = iou_rc; 36622d1d418eSSumit Saxena tm_req.DevHandle = htole16(handle); 36632d1d418eSSumit Saxena tm_req.TaskType = MPI3_SCSITASKMGMT_TASKTYPE_TARGET_RESET; 36642d1d418eSSumit Saxena tm_req.HostTag = htole16(drv_cmd->host_tag); 36652d1d418eSSumit Saxena tm_req.TaskHostTag = htole16(MPI3MR_HOSTTAG_INVALID); 36662d1d418eSSumit Saxena tm_req.Function = MPI3_FUNCTION_SCSI_TASK_MGMT; 36672d1d418eSSumit Saxena 36682d1d418eSSumit Saxena mpi3mr_set_bit(handle, sc->removepend_bitmap); 36692d1d418eSSumit Saxena retval = mpi3mr_submit_admin_cmd(sc, &tm_req, sizeof(tm_req)); 36702d1d418eSSumit Saxena if (retval) { 36712d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_ERROR, "%s :Issue DevRmHsTM: Admin Post failed\n", 36722d1d418eSSumit Saxena __func__); 36732d1d418eSSumit Saxena goto out_failed; 36742d1d418eSSumit Saxena } 36752d1d418eSSumit Saxena out: 36762d1d418eSSumit Saxena return; 36772d1d418eSSumit Saxena out_failed: 36782d1d418eSSumit Saxena drv_cmd->state = MPI3MR_CMD_NOTUSED; 36792d1d418eSSumit Saxena drv_cmd->callback = NULL; 36802d1d418eSSumit Saxena drv_cmd->dev_handle = MPI3MR_INVALID_DEV_HANDLE; 36812d1d418eSSumit Saxena drv_cmd->retry_count = 0; 36822d1d418eSSumit Saxena mpi3mr_clear_bit(cmd_idx, sc->devrem_bitmap); 36832d1d418eSSumit Saxena } 36842d1d418eSSumit Saxena 36852d1d418eSSumit Saxena /** 36862d1d418eSSumit Saxena * mpi3mr_complete_evt_ack - Event ack request completion 36872d1d418eSSumit Saxena * @sc: Adapter instance reference 36882d1d418eSSumit Saxena * @drv_cmd: Internal command tracker 36892d1d418eSSumit Saxena * 36902d1d418eSSumit Saxena * This is the completion handler for non blocking event 36912d1d418eSSumit Saxena * acknowledgment sent to the firmware and this will issue any 36922d1d418eSSumit Saxena * pending event acknowledgment request. 36932d1d418eSSumit Saxena * 36942d1d418eSSumit Saxena * Return: Nothing 36952d1d418eSSumit Saxena */ 36962d1d418eSSumit Saxena static void mpi3mr_complete_evt_ack(struct mpi3mr_softc *sc, 36972d1d418eSSumit Saxena struct mpi3mr_drvr_cmd *drv_cmd) 36982d1d418eSSumit Saxena { 36992d1d418eSSumit Saxena U16 cmd_idx = drv_cmd->host_tag - MPI3MR_HOSTTAG_EVTACKCMD_MIN; 37002d1d418eSSumit Saxena struct delayed_evtack_node *delayed_evtack = NULL; 37012d1d418eSSumit Saxena 37022d1d418eSSumit Saxena if (drv_cmd->ioc_status != MPI3_IOCSTATUS_SUCCESS) { 37032d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_EVENT, 37042d1d418eSSumit Saxena "%s: Failed IOCStatus(0x%04x) Loginfo(0x%08x)\n", __func__, 37052d1d418eSSumit Saxena (drv_cmd->ioc_status & MPI3_IOCSTATUS_STATUS_MASK), 37062d1d418eSSumit Saxena drv_cmd->ioc_loginfo); 37072d1d418eSSumit Saxena } 37082d1d418eSSumit Saxena 37092d1d418eSSumit Saxena if (!TAILQ_EMPTY(&sc->delayed_evtack_cmds_list)) { 37102d1d418eSSumit Saxena delayed_evtack = TAILQ_FIRST(&sc->delayed_evtack_cmds_list); 37112d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_EVENT, 37122d1d418eSSumit Saxena "%s: processing delayed event ack for event %d\n", 37132d1d418eSSumit Saxena __func__, delayed_evtack->event); 37142d1d418eSSumit Saxena mpi3mr_send_evt_ack(sc, delayed_evtack->event, drv_cmd, 37152d1d418eSSumit Saxena delayed_evtack->event_ctx); 37162d1d418eSSumit Saxena TAILQ_REMOVE(&sc->delayed_evtack_cmds_list, delayed_evtack, list); 37172d1d418eSSumit Saxena free(delayed_evtack, M_MPI3MR); 37182d1d418eSSumit Saxena return; 37192d1d418eSSumit Saxena } 37202d1d418eSSumit Saxena drv_cmd->state = MPI3MR_CMD_NOTUSED; 37212d1d418eSSumit Saxena drv_cmd->callback = NULL; 37222d1d418eSSumit Saxena mpi3mr_clear_bit(cmd_idx, sc->evtack_cmds_bitmap); 37232d1d418eSSumit Saxena } 37242d1d418eSSumit Saxena 37252d1d418eSSumit Saxena /** 37262d1d418eSSumit Saxena * mpi3mr_send_evt_ack - Issue event acknwoledgment request 37272d1d418eSSumit Saxena * @sc: Adapter instance reference 37282d1d418eSSumit Saxena * @event: MPI3 event id 37292d1d418eSSumit Saxena * @cmdparam: Internal command tracker 37302d1d418eSSumit Saxena * @event_ctx: Event context 37312d1d418eSSumit Saxena * 37322d1d418eSSumit Saxena * Issues event acknowledgment request to the firmware if there 37332d1d418eSSumit Saxena * is a free command to send the event ack else it to a pend 37342d1d418eSSumit Saxena * list so that it will be processed on a completion of a prior 37352d1d418eSSumit Saxena * event acknowledgment . 37362d1d418eSSumit Saxena * 37372d1d418eSSumit Saxena * Return: Nothing 37382d1d418eSSumit Saxena */ 37392d1d418eSSumit Saxena static void mpi3mr_send_evt_ack(struct mpi3mr_softc *sc, U8 event, 37402d1d418eSSumit Saxena struct mpi3mr_drvr_cmd *cmdparam, U32 event_ctx) 37412d1d418eSSumit Saxena { 37422d1d418eSSumit Saxena Mpi3EventAckRequest_t evtack_req; 37432d1d418eSSumit Saxena int retval = 0; 37442d1d418eSSumit Saxena U8 retrycount = 5; 37452d1d418eSSumit Saxena U16 cmd_idx = MPI3MR_NUM_EVTACKCMD; 37462d1d418eSSumit Saxena struct mpi3mr_drvr_cmd *drv_cmd = cmdparam; 37472d1d418eSSumit Saxena struct delayed_evtack_node *delayed_evtack = NULL; 37482d1d418eSSumit Saxena 37492d1d418eSSumit Saxena if (drv_cmd) 37502d1d418eSSumit Saxena goto issue_cmd; 37512d1d418eSSumit Saxena do { 37522d1d418eSSumit Saxena cmd_idx = mpi3mr_find_first_zero_bit(sc->evtack_cmds_bitmap, 37532d1d418eSSumit Saxena MPI3MR_NUM_EVTACKCMD); 37542d1d418eSSumit Saxena if (cmd_idx < MPI3MR_NUM_EVTACKCMD) { 37552d1d418eSSumit Saxena if (!mpi3mr_test_and_set_bit(cmd_idx, 37562d1d418eSSumit Saxena sc->evtack_cmds_bitmap)) 37572d1d418eSSumit Saxena break; 37582d1d418eSSumit Saxena cmd_idx = MPI3MR_NUM_EVTACKCMD; 37592d1d418eSSumit Saxena } 37602d1d418eSSumit Saxena } while (retrycount--); 37612d1d418eSSumit Saxena 37622d1d418eSSumit Saxena if (cmd_idx >= MPI3MR_NUM_EVTACKCMD) { 37632d1d418eSSumit Saxena delayed_evtack = malloc(sizeof(*delayed_evtack),M_MPI3MR, 37642d1d418eSSumit Saxena M_ZERO | M_NOWAIT); 37652d1d418eSSumit Saxena if (!delayed_evtack) 37662d1d418eSSumit Saxena return; 37672d1d418eSSumit Saxena delayed_evtack->event = event; 37682d1d418eSSumit Saxena delayed_evtack->event_ctx = event_ctx; 37692d1d418eSSumit Saxena TAILQ_INSERT_TAIL(&(sc->delayed_evtack_cmds_list), delayed_evtack, list); 37702d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_EVENT, "%s : Event ack for event:%d is postponed\n", 37712d1d418eSSumit Saxena __func__, event); 37722d1d418eSSumit Saxena return; 37732d1d418eSSumit Saxena } 37742d1d418eSSumit Saxena drv_cmd = &sc->evtack_cmds[cmd_idx]; 37752d1d418eSSumit Saxena 37762d1d418eSSumit Saxena issue_cmd: 37772d1d418eSSumit Saxena cmd_idx = drv_cmd->host_tag - MPI3MR_HOSTTAG_EVTACKCMD_MIN; 37782d1d418eSSumit Saxena 37792d1d418eSSumit Saxena memset(&evtack_req, 0, sizeof(evtack_req)); 37802d1d418eSSumit Saxena if (drv_cmd->state & MPI3MR_CMD_PENDING) { 37812d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_EVENT, "%s: Command is in use\n", __func__); 37822d1d418eSSumit Saxena goto out; 37832d1d418eSSumit Saxena } 37842d1d418eSSumit Saxena drv_cmd->state = MPI3MR_CMD_PENDING; 37852d1d418eSSumit Saxena drv_cmd->is_waiting = 0; 37862d1d418eSSumit Saxena drv_cmd->callback = mpi3mr_complete_evt_ack; 37872d1d418eSSumit Saxena evtack_req.HostTag = htole16(drv_cmd->host_tag); 37882d1d418eSSumit Saxena evtack_req.Function = MPI3_FUNCTION_EVENT_ACK; 37892d1d418eSSumit Saxena evtack_req.Event = event; 37902d1d418eSSumit Saxena evtack_req.EventContext = htole32(event_ctx); 37912d1d418eSSumit Saxena retval = mpi3mr_submit_admin_cmd(sc, &evtack_req, 37922d1d418eSSumit Saxena sizeof(evtack_req)); 37932d1d418eSSumit Saxena 37942d1d418eSSumit Saxena if (retval) { 37952d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_ERROR, "%s: Admin Post failed\n", __func__); 37962d1d418eSSumit Saxena goto out_failed; 37972d1d418eSSumit Saxena } 37982d1d418eSSumit Saxena out: 37992d1d418eSSumit Saxena return; 38002d1d418eSSumit Saxena out_failed: 38012d1d418eSSumit Saxena drv_cmd->state = MPI3MR_CMD_NOTUSED; 38022d1d418eSSumit Saxena drv_cmd->callback = NULL; 38032d1d418eSSumit Saxena mpi3mr_clear_bit(cmd_idx, sc->evtack_cmds_bitmap); 38042d1d418eSSumit Saxena } 38052d1d418eSSumit Saxena 38062d1d418eSSumit Saxena /* 38072d1d418eSSumit Saxena * mpi3mr_pcietopochg_evt_th - PCIETopologyChange evt tophalf 38082d1d418eSSumit Saxena * @sc: Adapter instance reference 38092d1d418eSSumit Saxena * @event_reply: Event data 38102d1d418eSSumit Saxena * 38112d1d418eSSumit Saxena * Checks for the reason code and based on that either block I/O 38122d1d418eSSumit Saxena * to device, or unblock I/O to the device, or start the device 38132d1d418eSSumit Saxena * removal handshake with reason as remove with the firmware for 38142d1d418eSSumit Saxena * PCIe devices. 38152d1d418eSSumit Saxena * 38162d1d418eSSumit Saxena * Return: Nothing 38172d1d418eSSumit Saxena */ 38182d1d418eSSumit Saxena static void mpi3mr_pcietopochg_evt_th(struct mpi3mr_softc *sc, 38192d1d418eSSumit Saxena Mpi3EventNotificationReply_t *event_reply) 38202d1d418eSSumit Saxena { 38212d1d418eSSumit Saxena Mpi3EventDataPcieTopologyChangeList_t *topo_evt = 38222d1d418eSSumit Saxena (Mpi3EventDataPcieTopologyChangeList_t *) event_reply->EventData; 38232d1d418eSSumit Saxena int i; 38242d1d418eSSumit Saxena U16 handle; 38252d1d418eSSumit Saxena U8 reason_code; 38262d1d418eSSumit Saxena struct mpi3mr_target *tgtdev = NULL; 38272d1d418eSSumit Saxena 38282d1d418eSSumit Saxena for (i = 0; i < topo_evt->NumEntries; i++) { 38292d1d418eSSumit Saxena handle = le16toh(topo_evt->PortEntry[i].AttachedDevHandle); 38302d1d418eSSumit Saxena if (!handle) 38312d1d418eSSumit Saxena continue; 38322d1d418eSSumit Saxena reason_code = topo_evt->PortEntry[i].PortStatus; 38332d1d418eSSumit Saxena tgtdev = mpi3mr_find_target_by_dev_handle(sc->cam_sc, handle); 38342d1d418eSSumit Saxena switch (reason_code) { 38352d1d418eSSumit Saxena case MPI3_EVENT_PCIE_TOPO_PS_NOT_RESPONDING: 38362d1d418eSSumit Saxena if (tgtdev) { 38372d1d418eSSumit Saxena tgtdev->dev_removed = 1; 38382d1d418eSSumit Saxena tgtdev->dev_removedelay = 0; 38392d1d418eSSumit Saxena mpi3mr_atomic_set(&tgtdev->block_io, 0); 38402d1d418eSSumit Saxena } 38412d1d418eSSumit Saxena mpi3mr_dev_rmhs_send_tm(sc, handle, NULL, 38422d1d418eSSumit Saxena MPI3_CTRL_OP_REMOVE_DEVICE); 38432d1d418eSSumit Saxena break; 38442d1d418eSSumit Saxena case MPI3_EVENT_PCIE_TOPO_PS_DELAY_NOT_RESPONDING: 38452d1d418eSSumit Saxena if (tgtdev) { 38462d1d418eSSumit Saxena tgtdev->dev_removedelay = 1; 38472d1d418eSSumit Saxena mpi3mr_atomic_inc(&tgtdev->block_io); 38482d1d418eSSumit Saxena } 38492d1d418eSSumit Saxena break; 38502d1d418eSSumit Saxena case MPI3_EVENT_PCIE_TOPO_PS_RESPONDING: 38512d1d418eSSumit Saxena if (tgtdev && 38522d1d418eSSumit Saxena tgtdev->dev_removedelay) { 38532d1d418eSSumit Saxena tgtdev->dev_removedelay = 0; 38542d1d418eSSumit Saxena if (mpi3mr_atomic_read(&tgtdev->block_io) > 0) 38552d1d418eSSumit Saxena mpi3mr_atomic_dec(&tgtdev->block_io); 38562d1d418eSSumit Saxena } 38572d1d418eSSumit Saxena break; 38582d1d418eSSumit Saxena case MPI3_EVENT_PCIE_TOPO_PS_PORT_CHANGED: 38592d1d418eSSumit Saxena default: 38602d1d418eSSumit Saxena break; 38612d1d418eSSumit Saxena } 38622d1d418eSSumit Saxena } 38632d1d418eSSumit Saxena } 38642d1d418eSSumit Saxena 38652d1d418eSSumit Saxena /** 38662d1d418eSSumit Saxena * mpi3mr_sastopochg_evt_th - SASTopologyChange evt tophalf 38672d1d418eSSumit Saxena * @sc: Adapter instance reference 38682d1d418eSSumit Saxena * @event_reply: Event data 38692d1d418eSSumit Saxena * 38702d1d418eSSumit Saxena * Checks for the reason code and based on that either block I/O 38712d1d418eSSumit Saxena * to device, or unblock I/O to the device, or start the device 38722d1d418eSSumit Saxena * removal handshake with reason as remove with the firmware for 38732d1d418eSSumit Saxena * SAS/SATA devices. 38742d1d418eSSumit Saxena * 38752d1d418eSSumit Saxena * Return: Nothing 38762d1d418eSSumit Saxena */ 38772d1d418eSSumit Saxena static void mpi3mr_sastopochg_evt_th(struct mpi3mr_softc *sc, 38782d1d418eSSumit Saxena Mpi3EventNotificationReply_t *event_reply) 38792d1d418eSSumit Saxena { 38802d1d418eSSumit Saxena Mpi3EventDataSasTopologyChangeList_t *topo_evt = 38812d1d418eSSumit Saxena (Mpi3EventDataSasTopologyChangeList_t *)event_reply->EventData; 38822d1d418eSSumit Saxena int i; 38832d1d418eSSumit Saxena U16 handle; 38842d1d418eSSumit Saxena U8 reason_code; 38852d1d418eSSumit Saxena struct mpi3mr_target *tgtdev = NULL; 38862d1d418eSSumit Saxena 38872d1d418eSSumit Saxena for (i = 0; i < topo_evt->NumEntries; i++) { 38882d1d418eSSumit Saxena handle = le16toh(topo_evt->PhyEntry[i].AttachedDevHandle); 38892d1d418eSSumit Saxena if (!handle) 38902d1d418eSSumit Saxena continue; 3891baabb919SChandrakanth patil reason_code = topo_evt->PhyEntry[i].PhyStatus & 38922d1d418eSSumit Saxena MPI3_EVENT_SAS_TOPO_PHY_RC_MASK; 38932d1d418eSSumit Saxena tgtdev = mpi3mr_find_target_by_dev_handle(sc->cam_sc, handle); 38942d1d418eSSumit Saxena switch (reason_code) { 38952d1d418eSSumit Saxena case MPI3_EVENT_SAS_TOPO_PHY_RC_TARG_NOT_RESPONDING: 38962d1d418eSSumit Saxena if (tgtdev) { 38972d1d418eSSumit Saxena tgtdev->dev_removed = 1; 38982d1d418eSSumit Saxena tgtdev->dev_removedelay = 0; 38992d1d418eSSumit Saxena mpi3mr_atomic_set(&tgtdev->block_io, 0); 39002d1d418eSSumit Saxena } 39012d1d418eSSumit Saxena mpi3mr_dev_rmhs_send_tm(sc, handle, NULL, 39022d1d418eSSumit Saxena MPI3_CTRL_OP_REMOVE_DEVICE); 39032d1d418eSSumit Saxena break; 39042d1d418eSSumit Saxena case MPI3_EVENT_SAS_TOPO_PHY_RC_DELAY_NOT_RESPONDING: 39052d1d418eSSumit Saxena if (tgtdev) { 39062d1d418eSSumit Saxena tgtdev->dev_removedelay = 1; 39072d1d418eSSumit Saxena mpi3mr_atomic_inc(&tgtdev->block_io); 39082d1d418eSSumit Saxena } 39092d1d418eSSumit Saxena break; 39102d1d418eSSumit Saxena case MPI3_EVENT_SAS_TOPO_PHY_RC_RESPONDING: 39112d1d418eSSumit Saxena if (tgtdev && 39122d1d418eSSumit Saxena tgtdev->dev_removedelay) { 39132d1d418eSSumit Saxena tgtdev->dev_removedelay = 0; 39142d1d418eSSumit Saxena if (mpi3mr_atomic_read(&tgtdev->block_io) > 0) 39152d1d418eSSumit Saxena mpi3mr_atomic_dec(&tgtdev->block_io); 39162d1d418eSSumit Saxena } 39172d1d418eSSumit Saxena case MPI3_EVENT_SAS_TOPO_PHY_RC_PHY_CHANGED: 39182d1d418eSSumit Saxena default: 39192d1d418eSSumit Saxena break; 39202d1d418eSSumit Saxena } 39212d1d418eSSumit Saxena } 39222d1d418eSSumit Saxena 39232d1d418eSSumit Saxena } 39242d1d418eSSumit Saxena /** 39252d1d418eSSumit Saxena * mpi3mr_devstatuschg_evt_th - DeviceStatusChange evt tophalf 39262d1d418eSSumit Saxena * @sc: Adapter instance reference 39272d1d418eSSumit Saxena * @event_reply: Event data 39282d1d418eSSumit Saxena * 39292d1d418eSSumit Saxena * Checks for the reason code and based on that either block I/O 39302d1d418eSSumit Saxena * to device, or unblock I/O to the device, or start the device 39312d1d418eSSumit Saxena * removal handshake with reason as remove/hide acknowledgment 39322d1d418eSSumit Saxena * with the firmware. 39332d1d418eSSumit Saxena * 39342d1d418eSSumit Saxena * Return: Nothing 39352d1d418eSSumit Saxena */ 39362d1d418eSSumit Saxena static void mpi3mr_devstatuschg_evt_th(struct mpi3mr_softc *sc, 39372d1d418eSSumit Saxena Mpi3EventNotificationReply_t *event_reply) 39382d1d418eSSumit Saxena { 39392d1d418eSSumit Saxena U16 dev_handle = 0; 39402d1d418eSSumit Saxena U8 ublock = 0, block = 0, hide = 0, uhide = 0, delete = 0, remove = 0; 39412d1d418eSSumit Saxena struct mpi3mr_target *tgtdev = NULL; 39422d1d418eSSumit Saxena Mpi3EventDataDeviceStatusChange_t *evtdata = 39432d1d418eSSumit Saxena (Mpi3EventDataDeviceStatusChange_t *) event_reply->EventData; 39442d1d418eSSumit Saxena 39452d1d418eSSumit Saxena dev_handle = le16toh(evtdata->DevHandle); 39462d1d418eSSumit Saxena 39472d1d418eSSumit Saxena switch (evtdata->ReasonCode) { 39482d1d418eSSumit Saxena case MPI3_EVENT_DEV_STAT_RC_INT_DEVICE_RESET_STRT: 39492d1d418eSSumit Saxena case MPI3_EVENT_DEV_STAT_RC_INT_IT_NEXUS_RESET_STRT: 39502d1d418eSSumit Saxena block = 1; 39512d1d418eSSumit Saxena break; 39522d1d418eSSumit Saxena case MPI3_EVENT_DEV_STAT_RC_HIDDEN: 39532d1d418eSSumit Saxena delete = 1; 39542d1d418eSSumit Saxena hide = 1; 39552d1d418eSSumit Saxena break; 39562d1d418eSSumit Saxena case MPI3_EVENT_DEV_STAT_RC_NOT_HIDDEN: 39572d1d418eSSumit Saxena uhide = 1; 39582d1d418eSSumit Saxena break; 39592d1d418eSSumit Saxena case MPI3_EVENT_DEV_STAT_RC_VD_NOT_RESPONDING: 39602d1d418eSSumit Saxena delete = 1; 39612d1d418eSSumit Saxena remove = 1; 39622d1d418eSSumit Saxena break; 39632d1d418eSSumit Saxena case MPI3_EVENT_DEV_STAT_RC_INT_DEVICE_RESET_CMP: 39642d1d418eSSumit Saxena case MPI3_EVENT_DEV_STAT_RC_INT_IT_NEXUS_RESET_CMP: 39652d1d418eSSumit Saxena ublock = 1; 39662d1d418eSSumit Saxena break; 39672d1d418eSSumit Saxena default: 39682d1d418eSSumit Saxena break; 39692d1d418eSSumit Saxena } 39702d1d418eSSumit Saxena 39712d1d418eSSumit Saxena tgtdev = mpi3mr_find_target_by_dev_handle(sc->cam_sc, dev_handle); 39722d1d418eSSumit Saxena 39732d1d418eSSumit Saxena if (!tgtdev) { 39742d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_ERROR, "%s :target with dev_handle:0x%x not found\n", 39752d1d418eSSumit Saxena __func__, dev_handle); 39762d1d418eSSumit Saxena return; 39772d1d418eSSumit Saxena } 39782d1d418eSSumit Saxena 39792d1d418eSSumit Saxena if (block) 39802d1d418eSSumit Saxena mpi3mr_atomic_inc(&tgtdev->block_io); 39812d1d418eSSumit Saxena 39822d1d418eSSumit Saxena if (hide) 39832d1d418eSSumit Saxena tgtdev->is_hidden = hide; 39842d1d418eSSumit Saxena 39852d1d418eSSumit Saxena if (uhide) { 39862d1d418eSSumit Saxena tgtdev->is_hidden = 0; 39872d1d418eSSumit Saxena tgtdev->dev_removed = 0; 39882d1d418eSSumit Saxena } 39892d1d418eSSumit Saxena 39902d1d418eSSumit Saxena if (delete) 39912d1d418eSSumit Saxena tgtdev->dev_removed = 1; 39922d1d418eSSumit Saxena 39932d1d418eSSumit Saxena if (ublock) { 39942d1d418eSSumit Saxena if (mpi3mr_atomic_read(&tgtdev->block_io) > 0) 39952d1d418eSSumit Saxena mpi3mr_atomic_dec(&tgtdev->block_io); 39962d1d418eSSumit Saxena } 39972d1d418eSSumit Saxena 39982d1d418eSSumit Saxena if (remove) { 39992d1d418eSSumit Saxena mpi3mr_dev_rmhs_send_tm(sc, dev_handle, NULL, 40002d1d418eSSumit Saxena MPI3_CTRL_OP_REMOVE_DEVICE); 40012d1d418eSSumit Saxena } 40022d1d418eSSumit Saxena if (hide) 40032d1d418eSSumit Saxena mpi3mr_dev_rmhs_send_tm(sc, dev_handle, NULL, 40042d1d418eSSumit Saxena MPI3_CTRL_OP_HIDDEN_ACK); 40052d1d418eSSumit Saxena } 40062d1d418eSSumit Saxena 40072d1d418eSSumit Saxena /** 40082d1d418eSSumit Saxena * mpi3mr_preparereset_evt_th - Prepareforreset evt tophalf 40092d1d418eSSumit Saxena * @sc: Adapter instance reference 40102d1d418eSSumit Saxena * @event_reply: Event data 40112d1d418eSSumit Saxena * 40122d1d418eSSumit Saxena * Blocks and unblocks host level I/O based on the reason code 40132d1d418eSSumit Saxena * 40142d1d418eSSumit Saxena * Return: Nothing 40152d1d418eSSumit Saxena */ 40162d1d418eSSumit Saxena static void mpi3mr_preparereset_evt_th(struct mpi3mr_softc *sc, 40172d1d418eSSumit Saxena Mpi3EventNotificationReply_t *event_reply) 40182d1d418eSSumit Saxena { 40192d1d418eSSumit Saxena Mpi3EventDataPrepareForReset_t *evtdata = 40202d1d418eSSumit Saxena (Mpi3EventDataPrepareForReset_t *)event_reply->EventData; 40212d1d418eSSumit Saxena 40222d1d418eSSumit Saxena if (evtdata->ReasonCode == MPI3_EVENT_PREPARE_RESET_RC_START) { 40232d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_EVENT, "%s :Recieved PrepForReset Event with RC=START\n", 40242d1d418eSSumit Saxena __func__); 40252d1d418eSSumit Saxena if (sc->prepare_for_reset) 40262d1d418eSSumit Saxena return; 40272d1d418eSSumit Saxena sc->prepare_for_reset = 1; 40282d1d418eSSumit Saxena sc->prepare_for_reset_timeout_counter = 0; 40292d1d418eSSumit Saxena } else if (evtdata->ReasonCode == MPI3_EVENT_PREPARE_RESET_RC_ABORT) { 40302d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_EVENT, "%s :Recieved PrepForReset Event with RC=ABORT\n", 40312d1d418eSSumit Saxena __func__); 40322d1d418eSSumit Saxena sc->prepare_for_reset = 0; 40332d1d418eSSumit Saxena sc->prepare_for_reset_timeout_counter = 0; 40342d1d418eSSumit Saxena } 40352d1d418eSSumit Saxena if ((event_reply->MsgFlags & MPI3_EVENT_NOTIFY_MSGFLAGS_ACK_MASK) 40362d1d418eSSumit Saxena == MPI3_EVENT_NOTIFY_MSGFLAGS_ACK_REQUIRED) 40372d1d418eSSumit Saxena mpi3mr_send_evt_ack(sc, event_reply->Event, NULL, 40382d1d418eSSumit Saxena le32toh(event_reply->EventContext)); 40392d1d418eSSumit Saxena } 40402d1d418eSSumit Saxena 40412d1d418eSSumit Saxena /** 40422d1d418eSSumit Saxena * mpi3mr_energypackchg_evt_th - Energypackchange evt tophalf 40432d1d418eSSumit Saxena * @sc: Adapter instance reference 40442d1d418eSSumit Saxena * @event_reply: Event data 40452d1d418eSSumit Saxena * 40462d1d418eSSumit Saxena * Identifies the new shutdown timeout value and update. 40472d1d418eSSumit Saxena * 40482d1d418eSSumit Saxena * Return: Nothing 40492d1d418eSSumit Saxena */ 40502d1d418eSSumit Saxena static void mpi3mr_energypackchg_evt_th(struct mpi3mr_softc *sc, 40512d1d418eSSumit Saxena Mpi3EventNotificationReply_t *event_reply) 40522d1d418eSSumit Saxena { 40532d1d418eSSumit Saxena Mpi3EventDataEnergyPackChange_t *evtdata = 40542d1d418eSSumit Saxena (Mpi3EventDataEnergyPackChange_t *)event_reply->EventData; 40552d1d418eSSumit Saxena U16 shutdown_timeout = le16toh(evtdata->ShutdownTimeout); 40562d1d418eSSumit Saxena 40572d1d418eSSumit Saxena if (shutdown_timeout <= 0) { 40582d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_ERROR, 40592d1d418eSSumit Saxena "%s :Invalid Shutdown Timeout received = %d\n", 40602d1d418eSSumit Saxena __func__, shutdown_timeout); 40612d1d418eSSumit Saxena return; 40622d1d418eSSumit Saxena } 40632d1d418eSSumit Saxena 40642d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_EVENT, 40652d1d418eSSumit Saxena "%s :Previous Shutdown Timeout Value = %d New Shutdown Timeout Value = %d\n", 40662d1d418eSSumit Saxena __func__, sc->facts.shutdown_timeout, shutdown_timeout); 40672d1d418eSSumit Saxena sc->facts.shutdown_timeout = shutdown_timeout; 40682d1d418eSSumit Saxena } 40692d1d418eSSumit Saxena 40702d1d418eSSumit Saxena /** 40712d1d418eSSumit Saxena * mpi3mr_cablemgmt_evt_th - Cable mgmt evt tophalf 40722d1d418eSSumit Saxena * @sc: Adapter instance reference 40732d1d418eSSumit Saxena * @event_reply: Event data 40742d1d418eSSumit Saxena * 40752d1d418eSSumit Saxena * Displays Cable manegemt event details. 40762d1d418eSSumit Saxena * 40772d1d418eSSumit Saxena * Return: Nothing 40782d1d418eSSumit Saxena */ 40792d1d418eSSumit Saxena static void mpi3mr_cablemgmt_evt_th(struct mpi3mr_softc *sc, 40802d1d418eSSumit Saxena Mpi3EventNotificationReply_t *event_reply) 40812d1d418eSSumit Saxena { 40822d1d418eSSumit Saxena Mpi3EventDataCableManagement_t *evtdata = 40832d1d418eSSumit Saxena (Mpi3EventDataCableManagement_t *)event_reply->EventData; 40842d1d418eSSumit Saxena 40852d1d418eSSumit Saxena switch (evtdata->Status) { 40862d1d418eSSumit Saxena case MPI3_EVENT_CABLE_MGMT_STATUS_INSUFFICIENT_POWER: 40872d1d418eSSumit Saxena { 40882d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_INFO, "An active cable with ReceptacleID %d cannot be powered.\n" 40892d1d418eSSumit Saxena "Devices connected to this cable are not detected.\n" 40902d1d418eSSumit Saxena "This cable requires %d mW of power.\n", 40912d1d418eSSumit Saxena evtdata->ReceptacleID, 40922d1d418eSSumit Saxena le32toh(evtdata->ActiveCablePowerRequirement)); 40932d1d418eSSumit Saxena break; 40942d1d418eSSumit Saxena } 40952d1d418eSSumit Saxena case MPI3_EVENT_CABLE_MGMT_STATUS_DEGRADED: 40962d1d418eSSumit Saxena { 40972d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_INFO, "A cable with ReceptacleID %d is not running at optimal speed\n", 40982d1d418eSSumit Saxena evtdata->ReceptacleID); 40992d1d418eSSumit Saxena break; 41002d1d418eSSumit Saxena } 41012d1d418eSSumit Saxena default: 41022d1d418eSSumit Saxena break; 41032d1d418eSSumit Saxena } 41042d1d418eSSumit Saxena } 41052d1d418eSSumit Saxena 41062d1d418eSSumit Saxena /** 41072d1d418eSSumit Saxena * mpi3mr_process_events - Event's toph-half handler 41082d1d418eSSumit Saxena * @sc: Adapter instance reference 41092d1d418eSSumit Saxena * @event_reply: Event data 41102d1d418eSSumit Saxena * 41112d1d418eSSumit Saxena * Top half of event processing. 41122d1d418eSSumit Saxena * 41132d1d418eSSumit Saxena * Return: Nothing 41142d1d418eSSumit Saxena */ 41152d1d418eSSumit Saxena static void mpi3mr_process_events(struct mpi3mr_softc *sc, 41162d1d418eSSumit Saxena uintptr_t data, Mpi3EventNotificationReply_t *event_reply) 41172d1d418eSSumit Saxena { 41182d1d418eSSumit Saxena U16 evt_type; 41192d1d418eSSumit Saxena bool ack_req = 0, process_evt_bh = 0; 41202d1d418eSSumit Saxena struct mpi3mr_fw_event_work *fw_event; 41212d1d418eSSumit Saxena U16 sz; 41222d1d418eSSumit Saxena 41232d1d418eSSumit Saxena if (sc->mpi3mr_flags & MPI3MR_FLAGS_SHUTDOWN) 41242d1d418eSSumit Saxena goto out; 41252d1d418eSSumit Saxena 41262d1d418eSSumit Saxena if ((event_reply->MsgFlags & MPI3_EVENT_NOTIFY_MSGFLAGS_ACK_MASK) 41272d1d418eSSumit Saxena == MPI3_EVENT_NOTIFY_MSGFLAGS_ACK_REQUIRED) 41282d1d418eSSumit Saxena ack_req = 1; 41292d1d418eSSumit Saxena 41302d1d418eSSumit Saxena evt_type = event_reply->Event; 41312d1d418eSSumit Saxena 41322d1d418eSSumit Saxena switch (evt_type) { 41332d1d418eSSumit Saxena case MPI3_EVENT_DEVICE_ADDED: 41342d1d418eSSumit Saxena { 41352d1d418eSSumit Saxena Mpi3DevicePage0_t *dev_pg0 = 41362d1d418eSSumit Saxena (Mpi3DevicePage0_t *) event_reply->EventData; 41372d1d418eSSumit Saxena if (mpi3mr_create_device(sc, dev_pg0)) 41382d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_ERROR, 41392d1d418eSSumit Saxena "%s :Failed to add device in the device add event\n", 41402d1d418eSSumit Saxena __func__); 41412d1d418eSSumit Saxena else 41422d1d418eSSumit Saxena process_evt_bh = 1; 41432d1d418eSSumit Saxena break; 41442d1d418eSSumit Saxena } 41452d1d418eSSumit Saxena 41462d1d418eSSumit Saxena case MPI3_EVENT_DEVICE_STATUS_CHANGE: 41472d1d418eSSumit Saxena { 41482d1d418eSSumit Saxena process_evt_bh = 1; 41492d1d418eSSumit Saxena mpi3mr_devstatuschg_evt_th(sc, event_reply); 41502d1d418eSSumit Saxena break; 41512d1d418eSSumit Saxena } 41522d1d418eSSumit Saxena case MPI3_EVENT_SAS_TOPOLOGY_CHANGE_LIST: 41532d1d418eSSumit Saxena { 41542d1d418eSSumit Saxena process_evt_bh = 1; 41552d1d418eSSumit Saxena mpi3mr_sastopochg_evt_th(sc, event_reply); 41562d1d418eSSumit Saxena break; 41572d1d418eSSumit Saxena } 41582d1d418eSSumit Saxena case MPI3_EVENT_PCIE_TOPOLOGY_CHANGE_LIST: 41592d1d418eSSumit Saxena { 41602d1d418eSSumit Saxena process_evt_bh = 1; 41612d1d418eSSumit Saxena mpi3mr_pcietopochg_evt_th(sc, event_reply); 41622d1d418eSSumit Saxena break; 41632d1d418eSSumit Saxena } 41642d1d418eSSumit Saxena case MPI3_EVENT_PREPARE_FOR_RESET: 41652d1d418eSSumit Saxena { 41662d1d418eSSumit Saxena mpi3mr_preparereset_evt_th(sc, event_reply); 41672d1d418eSSumit Saxena ack_req = 0; 41682d1d418eSSumit Saxena break; 41692d1d418eSSumit Saxena } 41702d1d418eSSumit Saxena case MPI3_EVENT_DEVICE_INFO_CHANGED: 41712d1d418eSSumit Saxena case MPI3_EVENT_LOG_DATA: 41722d1d418eSSumit Saxena { 41732d1d418eSSumit Saxena process_evt_bh = 1; 41742d1d418eSSumit Saxena break; 41752d1d418eSSumit Saxena } 41762d1d418eSSumit Saxena case MPI3_EVENT_ENERGY_PACK_CHANGE: 41772d1d418eSSumit Saxena { 41782d1d418eSSumit Saxena mpi3mr_energypackchg_evt_th(sc, event_reply); 41792d1d418eSSumit Saxena break; 41802d1d418eSSumit Saxena } 41812d1d418eSSumit Saxena case MPI3_EVENT_CABLE_MGMT: 41822d1d418eSSumit Saxena { 41832d1d418eSSumit Saxena mpi3mr_cablemgmt_evt_th(sc, event_reply); 41842d1d418eSSumit Saxena break; 41852d1d418eSSumit Saxena } 41862d1d418eSSumit Saxena 41872d1d418eSSumit Saxena case MPI3_EVENT_ENCL_DEVICE_STATUS_CHANGE: 41882d1d418eSSumit Saxena case MPI3_EVENT_SAS_DISCOVERY: 41892d1d418eSSumit Saxena case MPI3_EVENT_SAS_DEVICE_DISCOVERY_ERROR: 41902d1d418eSSumit Saxena case MPI3_EVENT_SAS_BROADCAST_PRIMITIVE: 41912d1d418eSSumit Saxena case MPI3_EVENT_PCIE_ENUMERATION: 41922d1d418eSSumit Saxena break; 41932d1d418eSSumit Saxena default: 41942d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_INFO, "%s :Event 0x%02x is not handled by driver\n", 41952d1d418eSSumit Saxena __func__, evt_type); 41962d1d418eSSumit Saxena break; 41972d1d418eSSumit Saxena } 41982d1d418eSSumit Saxena 41992d1d418eSSumit Saxena if (process_evt_bh || ack_req) { 42002d1d418eSSumit Saxena fw_event = malloc(sizeof(struct mpi3mr_fw_event_work), M_MPI3MR, 42012d1d418eSSumit Saxena M_ZERO|M_NOWAIT); 42022d1d418eSSumit Saxena 42032d1d418eSSumit Saxena if (!fw_event) { 42042d1d418eSSumit Saxena printf("%s: allocate failed for fw_event\n", __func__); 42052d1d418eSSumit Saxena return; 42062d1d418eSSumit Saxena } 42072d1d418eSSumit Saxena 42082d1d418eSSumit Saxena sz = le16toh(event_reply->EventDataLength) * 4; 42092d1d418eSSumit Saxena fw_event->event_data = malloc(sz, M_MPI3MR, M_ZERO|M_NOWAIT); 42102d1d418eSSumit Saxena 42112d1d418eSSumit Saxena if (!fw_event->event_data) { 42122d1d418eSSumit Saxena printf("%s: allocate failed for event_data\n", __func__); 42132d1d418eSSumit Saxena free(fw_event, M_MPI3MR); 42142d1d418eSSumit Saxena return; 42152d1d418eSSumit Saxena } 42162d1d418eSSumit Saxena 42172d1d418eSSumit Saxena bcopy(event_reply->EventData, fw_event->event_data, sz); 42182d1d418eSSumit Saxena fw_event->event = event_reply->Event; 42192d1d418eSSumit Saxena if ((event_reply->Event == MPI3_EVENT_SAS_TOPOLOGY_CHANGE_LIST || 42202d1d418eSSumit Saxena event_reply->Event == MPI3_EVENT_PCIE_TOPOLOGY_CHANGE_LIST || 42212d1d418eSSumit Saxena event_reply->Event == MPI3_EVENT_ENCL_DEVICE_STATUS_CHANGE ) && 42222d1d418eSSumit Saxena sc->track_mapping_events) 42232d1d418eSSumit Saxena sc->pending_map_events++; 42242d1d418eSSumit Saxena 42252d1d418eSSumit Saxena /* 42262d1d418eSSumit Saxena * Events should be processed after Port enable is completed. 42272d1d418eSSumit Saxena */ 42282d1d418eSSumit Saxena if ((event_reply->Event == MPI3_EVENT_SAS_TOPOLOGY_CHANGE_LIST || 42292d1d418eSSumit Saxena event_reply->Event == MPI3_EVENT_PCIE_TOPOLOGY_CHANGE_LIST ) && 42302d1d418eSSumit Saxena !(sc->mpi3mr_flags & MPI3MR_FLAGS_PORT_ENABLE_DONE)) 42312d1d418eSSumit Saxena mpi3mr_startup_increment(sc->cam_sc); 42322d1d418eSSumit Saxena 42332d1d418eSSumit Saxena fw_event->send_ack = ack_req; 42342d1d418eSSumit Saxena fw_event->event_context = le32toh(event_reply->EventContext); 42352d1d418eSSumit Saxena fw_event->event_data_size = sz; 42362d1d418eSSumit Saxena fw_event->process_event = process_evt_bh; 42372d1d418eSSumit Saxena 42382d1d418eSSumit Saxena mtx_lock(&sc->fwevt_lock); 42392d1d418eSSumit Saxena TAILQ_INSERT_TAIL(&sc->cam_sc->ev_queue, fw_event, ev_link); 42402d1d418eSSumit Saxena taskqueue_enqueue(sc->cam_sc->ev_tq, &sc->cam_sc->ev_task); 42412d1d418eSSumit Saxena mtx_unlock(&sc->fwevt_lock); 42422d1d418eSSumit Saxena 42432d1d418eSSumit Saxena } 42442d1d418eSSumit Saxena out: 42452d1d418eSSumit Saxena return; 42462d1d418eSSumit Saxena } 42472d1d418eSSumit Saxena 42482d1d418eSSumit Saxena static void mpi3mr_handle_events(struct mpi3mr_softc *sc, uintptr_t data, 42492d1d418eSSumit Saxena Mpi3DefaultReply_t *def_reply) 42502d1d418eSSumit Saxena { 42512d1d418eSSumit Saxena Mpi3EventNotificationReply_t *event_reply = 42522d1d418eSSumit Saxena (Mpi3EventNotificationReply_t *)def_reply; 42532d1d418eSSumit Saxena 42542d1d418eSSumit Saxena sc->change_count = event_reply->IOCChangeCount; 42552d1d418eSSumit Saxena mpi3mr_display_event_data(sc, event_reply); 42562d1d418eSSumit Saxena 42572d1d418eSSumit Saxena mpi3mr_process_events(sc, data, event_reply); 42582d1d418eSSumit Saxena } 42592d1d418eSSumit Saxena 42602d1d418eSSumit Saxena static void mpi3mr_process_admin_reply_desc(struct mpi3mr_softc *sc, 42612d1d418eSSumit Saxena Mpi3DefaultReplyDescriptor_t *reply_desc, U64 *reply_dma) 42622d1d418eSSumit Saxena { 42632d1d418eSSumit Saxena U16 reply_desc_type, host_tag = 0, idx; 42642d1d418eSSumit Saxena U16 ioc_status = MPI3_IOCSTATUS_SUCCESS; 42652d1d418eSSumit Saxena U32 ioc_loginfo = 0; 42662d1d418eSSumit Saxena Mpi3StatusReplyDescriptor_t *status_desc; 42672d1d418eSSumit Saxena Mpi3AddressReplyDescriptor_t *addr_desc; 42682d1d418eSSumit Saxena Mpi3SuccessReplyDescriptor_t *success_desc; 42692d1d418eSSumit Saxena Mpi3DefaultReply_t *def_reply = NULL; 42702d1d418eSSumit Saxena struct mpi3mr_drvr_cmd *cmdptr = NULL; 42712d1d418eSSumit Saxena Mpi3SCSIIOReply_t *scsi_reply; 42722d1d418eSSumit Saxena U8 *sense_buf = NULL; 42732d1d418eSSumit Saxena 42742d1d418eSSumit Saxena *reply_dma = 0; 42752d1d418eSSumit Saxena reply_desc_type = reply_desc->ReplyFlags & 42762d1d418eSSumit Saxena MPI3_REPLY_DESCRIPT_FLAGS_TYPE_MASK; 42772d1d418eSSumit Saxena switch (reply_desc_type) { 42782d1d418eSSumit Saxena case MPI3_REPLY_DESCRIPT_FLAGS_TYPE_STATUS: 42792d1d418eSSumit Saxena status_desc = (Mpi3StatusReplyDescriptor_t *)reply_desc; 42802d1d418eSSumit Saxena host_tag = status_desc->HostTag; 42812d1d418eSSumit Saxena ioc_status = status_desc->IOCStatus; 4282baabb919SChandrakanth patil if (ioc_status & MPI3_IOCSTATUS_STATUS_MASK) 42832d1d418eSSumit Saxena ioc_loginfo = status_desc->IOCLogInfo; 4284baabb919SChandrakanth patil ioc_status &= MPI3_IOCSTATUS_STATUS_MASK; 42852d1d418eSSumit Saxena break; 42862d1d418eSSumit Saxena case MPI3_REPLY_DESCRIPT_FLAGS_TYPE_ADDRESS_REPLY: 42872d1d418eSSumit Saxena addr_desc = (Mpi3AddressReplyDescriptor_t *)reply_desc; 42882d1d418eSSumit Saxena *reply_dma = addr_desc->ReplyFrameAddress; 42892d1d418eSSumit Saxena def_reply = mpi3mr_get_reply_virt_addr(sc, *reply_dma); 42902d1d418eSSumit Saxena if (def_reply == NULL) 42912d1d418eSSumit Saxena goto out; 42922d1d418eSSumit Saxena host_tag = def_reply->HostTag; 42932d1d418eSSumit Saxena ioc_status = def_reply->IOCStatus; 4294baabb919SChandrakanth patil if (ioc_status & MPI3_IOCSTATUS_STATUS_MASK) 42952d1d418eSSumit Saxena ioc_loginfo = def_reply->IOCLogInfo; 4296baabb919SChandrakanth patil ioc_status &= MPI3_IOCSTATUS_STATUS_MASK; 42972d1d418eSSumit Saxena if (def_reply->Function == MPI3_FUNCTION_SCSI_IO) { 42982d1d418eSSumit Saxena scsi_reply = (Mpi3SCSIIOReply_t *)def_reply; 42992d1d418eSSumit Saxena sense_buf = mpi3mr_get_sensebuf_virt_addr(sc, 43002d1d418eSSumit Saxena scsi_reply->SenseDataBufferAddress); 43012d1d418eSSumit Saxena } 43022d1d418eSSumit Saxena break; 43032d1d418eSSumit Saxena case MPI3_REPLY_DESCRIPT_FLAGS_TYPE_SUCCESS: 43042d1d418eSSumit Saxena success_desc = (Mpi3SuccessReplyDescriptor_t *)reply_desc; 43052d1d418eSSumit Saxena host_tag = success_desc->HostTag; 43062d1d418eSSumit Saxena break; 43072d1d418eSSumit Saxena default: 43082d1d418eSSumit Saxena break; 43092d1d418eSSumit Saxena } 43102d1d418eSSumit Saxena switch (host_tag) { 43112d1d418eSSumit Saxena case MPI3MR_HOSTTAG_INITCMDS: 43122d1d418eSSumit Saxena cmdptr = &sc->init_cmds; 43132d1d418eSSumit Saxena break; 43142d1d418eSSumit Saxena case MPI3MR_HOSTTAG_IOCTLCMDS: 43152d1d418eSSumit Saxena cmdptr = &sc->ioctl_cmds; 43162d1d418eSSumit Saxena break; 43172d1d418eSSumit Saxena case MPI3MR_HOSTTAG_TMS: 43182d1d418eSSumit Saxena cmdptr = &sc->host_tm_cmds; 43192d1d418eSSumit Saxena wakeup((void *)&sc->tm_chan); 43202d1d418eSSumit Saxena break; 43212d1d418eSSumit Saxena case MPI3MR_HOSTTAG_PELABORT: 43222d1d418eSSumit Saxena cmdptr = &sc->pel_abort_cmd; 43232d1d418eSSumit Saxena break; 43242d1d418eSSumit Saxena case MPI3MR_HOSTTAG_PELWAIT: 43252d1d418eSSumit Saxena cmdptr = &sc->pel_cmds; 43262d1d418eSSumit Saxena break; 43272d1d418eSSumit Saxena case MPI3MR_HOSTTAG_INVALID: 43282d1d418eSSumit Saxena if (def_reply && def_reply->Function == 43292d1d418eSSumit Saxena MPI3_FUNCTION_EVENT_NOTIFICATION) 43302d1d418eSSumit Saxena mpi3mr_handle_events(sc, *reply_dma ,def_reply); 43312d1d418eSSumit Saxena default: 43322d1d418eSSumit Saxena break; 43332d1d418eSSumit Saxena } 43342d1d418eSSumit Saxena 43352d1d418eSSumit Saxena if (host_tag >= MPI3MR_HOSTTAG_DEVRMCMD_MIN && 43362d1d418eSSumit Saxena host_tag <= MPI3MR_HOSTTAG_DEVRMCMD_MAX ) { 43372d1d418eSSumit Saxena idx = host_tag - MPI3MR_HOSTTAG_DEVRMCMD_MIN; 43382d1d418eSSumit Saxena cmdptr = &sc->dev_rmhs_cmds[idx]; 43392d1d418eSSumit Saxena } 43402d1d418eSSumit Saxena 43412d1d418eSSumit Saxena if (host_tag >= MPI3MR_HOSTTAG_EVTACKCMD_MIN && 43422d1d418eSSumit Saxena host_tag <= MPI3MR_HOSTTAG_EVTACKCMD_MAX) { 43432d1d418eSSumit Saxena idx = host_tag - MPI3MR_HOSTTAG_EVTACKCMD_MIN; 43442d1d418eSSumit Saxena cmdptr = &sc->evtack_cmds[idx]; 43452d1d418eSSumit Saxena } 43462d1d418eSSumit Saxena 43472d1d418eSSumit Saxena if (cmdptr) { 43482d1d418eSSumit Saxena if (cmdptr->state & MPI3MR_CMD_PENDING) { 43492d1d418eSSumit Saxena cmdptr->state |= MPI3MR_CMD_COMPLETE; 43502d1d418eSSumit Saxena cmdptr->ioc_loginfo = ioc_loginfo; 43512d1d418eSSumit Saxena cmdptr->ioc_status = ioc_status; 43522d1d418eSSumit Saxena cmdptr->state &= ~MPI3MR_CMD_PENDING; 43532d1d418eSSumit Saxena if (def_reply) { 43542d1d418eSSumit Saxena cmdptr->state |= MPI3MR_CMD_REPLYVALID; 43552d1d418eSSumit Saxena memcpy((U8 *)cmdptr->reply, (U8 *)def_reply, 43562d1d418eSSumit Saxena sc->reply_sz); 43572d1d418eSSumit Saxena } 43582d1d418eSSumit Saxena if (sense_buf && cmdptr->sensebuf) { 43592d1d418eSSumit Saxena cmdptr->is_senseprst = 1; 43602d1d418eSSumit Saxena memcpy(cmdptr->sensebuf, sense_buf, 43612d1d418eSSumit Saxena MPI3MR_SENSEBUF_SZ); 43622d1d418eSSumit Saxena } 43632d1d418eSSumit Saxena if (cmdptr->is_waiting) { 43642d1d418eSSumit Saxena complete(&cmdptr->completion); 43652d1d418eSSumit Saxena cmdptr->is_waiting = 0; 43662d1d418eSSumit Saxena } else if (cmdptr->callback) 43672d1d418eSSumit Saxena cmdptr->callback(sc, cmdptr); 43682d1d418eSSumit Saxena } 43692d1d418eSSumit Saxena } 43702d1d418eSSumit Saxena out: 43712d1d418eSSumit Saxena if (sense_buf != NULL) 43722d1d418eSSumit Saxena mpi3mr_repost_sense_buf(sc, 43732d1d418eSSumit Saxena scsi_reply->SenseDataBufferAddress); 43742d1d418eSSumit Saxena return; 43752d1d418eSSumit Saxena } 43762d1d418eSSumit Saxena 43772d1d418eSSumit Saxena /* 43782d1d418eSSumit Saxena * mpi3mr_complete_admin_cmd: ISR routine for admin commands 43792d1d418eSSumit Saxena * @sc: Adapter's soft instance 43802d1d418eSSumit Saxena * 43812d1d418eSSumit Saxena * This function processes admin command completions. 43822d1d418eSSumit Saxena */ 43832d1d418eSSumit Saxena static int mpi3mr_complete_admin_cmd(struct mpi3mr_softc *sc) 43842d1d418eSSumit Saxena { 43852d1d418eSSumit Saxena U32 exp_phase = sc->admin_reply_ephase; 43862d1d418eSSumit Saxena U32 adm_reply_ci = sc->admin_reply_ci; 43872d1d418eSSumit Saxena U32 num_adm_reply = 0; 43882d1d418eSSumit Saxena U64 reply_dma = 0; 43892d1d418eSSumit Saxena Mpi3DefaultReplyDescriptor_t *reply_desc; 4390eb7a4b35SChandrakanth patil U16 threshold_comps = 0; 43912d1d418eSSumit Saxena 43922d1d418eSSumit Saxena mtx_lock_spin(&sc->admin_reply_lock); 43932d1d418eSSumit Saxena if (sc->admin_in_use == false) { 43942d1d418eSSumit Saxena sc->admin_in_use = true; 43952d1d418eSSumit Saxena mtx_unlock_spin(&sc->admin_reply_lock); 43962d1d418eSSumit Saxena } else { 43972d1d418eSSumit Saxena mtx_unlock_spin(&sc->admin_reply_lock); 43982d1d418eSSumit Saxena return 0; 43992d1d418eSSumit Saxena } 44002d1d418eSSumit Saxena 44012d1d418eSSumit Saxena reply_desc = (Mpi3DefaultReplyDescriptor_t *)sc->admin_reply + 44022d1d418eSSumit Saxena adm_reply_ci; 44032d1d418eSSumit Saxena 44042d1d418eSSumit Saxena if ((reply_desc->ReplyFlags & 44052d1d418eSSumit Saxena MPI3_REPLY_DESCRIPT_FLAGS_PHASE_MASK) != exp_phase) { 44062d1d418eSSumit Saxena mtx_lock_spin(&sc->admin_reply_lock); 44072d1d418eSSumit Saxena sc->admin_in_use = false; 44082d1d418eSSumit Saxena mtx_unlock_spin(&sc->admin_reply_lock); 44092d1d418eSSumit Saxena return 0; 44102d1d418eSSumit Saxena } 44112d1d418eSSumit Saxena 44122d1d418eSSumit Saxena do { 44132d1d418eSSumit Saxena sc->admin_req_ci = reply_desc->RequestQueueCI; 44142d1d418eSSumit Saxena mpi3mr_process_admin_reply_desc(sc, reply_desc, &reply_dma); 44152d1d418eSSumit Saxena if (reply_dma) 44162d1d418eSSumit Saxena mpi3mr_repost_reply_buf(sc, reply_dma); 44172d1d418eSSumit Saxena num_adm_reply++; 44182d1d418eSSumit Saxena if (++adm_reply_ci == sc->num_admin_replies) { 44192d1d418eSSumit Saxena adm_reply_ci = 0; 44202d1d418eSSumit Saxena exp_phase ^= 1; 44212d1d418eSSumit Saxena } 44222d1d418eSSumit Saxena reply_desc = 44232d1d418eSSumit Saxena (Mpi3DefaultReplyDescriptor_t *)sc->admin_reply + 44242d1d418eSSumit Saxena adm_reply_ci; 44252d1d418eSSumit Saxena if ((reply_desc->ReplyFlags & 44262d1d418eSSumit Saxena MPI3_REPLY_DESCRIPT_FLAGS_PHASE_MASK) != exp_phase) 44272d1d418eSSumit Saxena break; 4428eb7a4b35SChandrakanth patil 4429eb7a4b35SChandrakanth patil if (++threshold_comps == MPI3MR_THRESHOLD_REPLY_COUNT) { 4430eb7a4b35SChandrakanth patil mpi3mr_regwrite(sc, MPI3_SYSIF_ADMIN_REPLY_Q_CI_OFFSET, adm_reply_ci); 4431eb7a4b35SChandrakanth patil threshold_comps = 0; 4432eb7a4b35SChandrakanth patil } 44332d1d418eSSumit Saxena } while (1); 44342d1d418eSSumit Saxena 44352d1d418eSSumit Saxena mpi3mr_regwrite(sc, MPI3_SYSIF_ADMIN_REPLY_Q_CI_OFFSET, adm_reply_ci); 44362d1d418eSSumit Saxena sc->admin_reply_ci = adm_reply_ci; 44372d1d418eSSumit Saxena sc->admin_reply_ephase = exp_phase; 44382d1d418eSSumit Saxena mtx_lock_spin(&sc->admin_reply_lock); 44392d1d418eSSumit Saxena sc->admin_in_use = false; 44402d1d418eSSumit Saxena mtx_unlock_spin(&sc->admin_reply_lock); 44412d1d418eSSumit Saxena return num_adm_reply; 44422d1d418eSSumit Saxena } 44432d1d418eSSumit Saxena 44442d1d418eSSumit Saxena static void 44452d1d418eSSumit Saxena mpi3mr_cmd_done(struct mpi3mr_softc *sc, struct mpi3mr_cmd *cmd) 44462d1d418eSSumit Saxena { 44472d1d418eSSumit Saxena mpi3mr_unmap_request(sc, cmd); 44482d1d418eSSumit Saxena 44492d1d418eSSumit Saxena mtx_lock(&sc->mpi3mr_mtx); 44502d1d418eSSumit Saxena if (cmd->callout_owner) { 44512d1d418eSSumit Saxena callout_stop(&cmd->callout); 44522d1d418eSSumit Saxena cmd->callout_owner = false; 44532d1d418eSSumit Saxena } 44542d1d418eSSumit Saxena 44552d1d418eSSumit Saxena if (sc->unrecoverable) 44562d1d418eSSumit Saxena mpi3mr_set_ccbstatus(cmd->ccb, CAM_DEV_NOT_THERE); 44572d1d418eSSumit Saxena 44582d1d418eSSumit Saxena xpt_done(cmd->ccb); 44592d1d418eSSumit Saxena cmd->ccb = NULL; 44602d1d418eSSumit Saxena mtx_unlock(&sc->mpi3mr_mtx); 44612d1d418eSSumit Saxena mpi3mr_release_command(cmd); 44622d1d418eSSumit Saxena } 44632d1d418eSSumit Saxena 44642d1d418eSSumit Saxena void mpi3mr_process_op_reply_desc(struct mpi3mr_softc *sc, 44652d1d418eSSumit Saxena Mpi3DefaultReplyDescriptor_t *reply_desc, U64 *reply_dma) 44662d1d418eSSumit Saxena { 44672d1d418eSSumit Saxena U16 reply_desc_type, host_tag = 0; 44682d1d418eSSumit Saxena U16 ioc_status = MPI3_IOCSTATUS_SUCCESS; 44692d1d418eSSumit Saxena U32 ioc_loginfo = 0; 44702d1d418eSSumit Saxena Mpi3StatusReplyDescriptor_t *status_desc = NULL; 44712d1d418eSSumit Saxena Mpi3AddressReplyDescriptor_t *addr_desc = NULL; 44722d1d418eSSumit Saxena Mpi3SuccessReplyDescriptor_t *success_desc = NULL; 44732d1d418eSSumit Saxena Mpi3SCSIIOReply_t *scsi_reply = NULL; 44742d1d418eSSumit Saxena U8 *sense_buf = NULL; 44752d1d418eSSumit Saxena U8 scsi_state = 0, scsi_status = 0, sense_state = 0; 44762d1d418eSSumit Saxena U32 xfer_count = 0, sense_count =0, resp_data = 0; 44772d1d418eSSumit Saxena struct mpi3mr_cmd *cm = NULL; 44782d1d418eSSumit Saxena union ccb *ccb; 44792d1d418eSSumit Saxena struct ccb_scsiio *csio; 44802d1d418eSSumit Saxena struct mpi3mr_cam_softc *cam_sc; 44812d1d418eSSumit Saxena U32 target_id; 44822d1d418eSSumit Saxena U8 *scsi_cdb; 44832d1d418eSSumit Saxena struct mpi3mr_target *target = NULL; 44842d1d418eSSumit Saxena U32 ioc_pend_data_len = 0, tg_pend_data_len = 0, data_len_blks = 0; 44852d1d418eSSumit Saxena struct mpi3mr_throttle_group_info *tg = NULL; 44862d1d418eSSumit Saxena U8 throttle_enabled_dev = 0; 44872d1d418eSSumit Saxena static int ratelimit; 44882d1d418eSSumit Saxena 44892d1d418eSSumit Saxena *reply_dma = 0; 44902d1d418eSSumit Saxena reply_desc_type = reply_desc->ReplyFlags & 44912d1d418eSSumit Saxena MPI3_REPLY_DESCRIPT_FLAGS_TYPE_MASK; 44922d1d418eSSumit Saxena switch (reply_desc_type) { 44932d1d418eSSumit Saxena case MPI3_REPLY_DESCRIPT_FLAGS_TYPE_STATUS: 44942d1d418eSSumit Saxena status_desc = (Mpi3StatusReplyDescriptor_t *)reply_desc; 44952d1d418eSSumit Saxena host_tag = status_desc->HostTag; 44962d1d418eSSumit Saxena ioc_status = status_desc->IOCStatus; 4497baabb919SChandrakanth patil if (ioc_status & MPI3_IOCSTATUS_STATUS_MASK) 44982d1d418eSSumit Saxena ioc_loginfo = status_desc->IOCLogInfo; 4499baabb919SChandrakanth patil ioc_status &= MPI3_IOCSTATUS_STATUS_MASK; 45002d1d418eSSumit Saxena break; 45012d1d418eSSumit Saxena case MPI3_REPLY_DESCRIPT_FLAGS_TYPE_ADDRESS_REPLY: 45022d1d418eSSumit Saxena addr_desc = (Mpi3AddressReplyDescriptor_t *)reply_desc; 45032d1d418eSSumit Saxena *reply_dma = addr_desc->ReplyFrameAddress; 45042d1d418eSSumit Saxena scsi_reply = mpi3mr_get_reply_virt_addr(sc, 45052d1d418eSSumit Saxena *reply_dma); 45062d1d418eSSumit Saxena if (scsi_reply == NULL) { 45072d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_ERROR, "scsi_reply is NULL, " 45082d1d418eSSumit Saxena "this shouldn't happen, reply_desc: %p\n", 45092d1d418eSSumit Saxena reply_desc); 45102d1d418eSSumit Saxena goto out; 45112d1d418eSSumit Saxena } 45122d1d418eSSumit Saxena 45132d1d418eSSumit Saxena host_tag = scsi_reply->HostTag; 45142d1d418eSSumit Saxena ioc_status = scsi_reply->IOCStatus; 45152d1d418eSSumit Saxena scsi_status = scsi_reply->SCSIStatus; 45162d1d418eSSumit Saxena scsi_state = scsi_reply->SCSIState; 45172d1d418eSSumit Saxena sense_state = (scsi_state & MPI3_SCSI_STATE_SENSE_MASK); 45182d1d418eSSumit Saxena xfer_count = scsi_reply->TransferCount; 45192d1d418eSSumit Saxena sense_count = scsi_reply->SenseCount; 45202d1d418eSSumit Saxena resp_data = scsi_reply->ResponseData; 45212d1d418eSSumit Saxena sense_buf = mpi3mr_get_sensebuf_virt_addr(sc, 45222d1d418eSSumit Saxena scsi_reply->SenseDataBufferAddress); 4523baabb919SChandrakanth patil if (ioc_status & MPI3_IOCSTATUS_STATUS_MASK) 45242d1d418eSSumit Saxena ioc_loginfo = scsi_reply->IOCLogInfo; 4525baabb919SChandrakanth patil ioc_status &= MPI3_IOCSTATUS_STATUS_MASK; 45262d1d418eSSumit Saxena if (sense_state == MPI3_SCSI_STATE_SENSE_BUFF_Q_EMPTY) 45272d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_ERROR, "Ran out of sense buffers\n"); 45282d1d418eSSumit Saxena 45292d1d418eSSumit Saxena break; 45302d1d418eSSumit Saxena case MPI3_REPLY_DESCRIPT_FLAGS_TYPE_SUCCESS: 45312d1d418eSSumit Saxena success_desc = (Mpi3SuccessReplyDescriptor_t *)reply_desc; 45322d1d418eSSumit Saxena host_tag = success_desc->HostTag; 45332d1d418eSSumit Saxena 45342d1d418eSSumit Saxena default: 45352d1d418eSSumit Saxena break; 45362d1d418eSSumit Saxena } 45372d1d418eSSumit Saxena 45382d1d418eSSumit Saxena cm = sc->cmd_list[host_tag]; 45392d1d418eSSumit Saxena 45402d1d418eSSumit Saxena if (cm->state == MPI3MR_CMD_STATE_FREE) 45412d1d418eSSumit Saxena goto out; 45422d1d418eSSumit Saxena 45432d1d418eSSumit Saxena cam_sc = sc->cam_sc; 45442d1d418eSSumit Saxena ccb = cm->ccb; 45452d1d418eSSumit Saxena csio = &ccb->csio; 45462d1d418eSSumit Saxena target_id = csio->ccb_h.target_id; 45472d1d418eSSumit Saxena 45482d1d418eSSumit Saxena scsi_cdb = scsiio_cdb_ptr(csio); 45492d1d418eSSumit Saxena 45502d1d418eSSumit Saxena target = mpi3mr_find_target_by_per_id(cam_sc, target_id); 45512d1d418eSSumit Saxena if (sc->iot_enable) { 45522d1d418eSSumit Saxena data_len_blks = csio->dxfer_len >> 9; 45532d1d418eSSumit Saxena 45542d1d418eSSumit Saxena if (target) { 45552d1d418eSSumit Saxena tg = target->throttle_group; 45562d1d418eSSumit Saxena throttle_enabled_dev = 45572d1d418eSSumit Saxena target->io_throttle_enabled; 45582d1d418eSSumit Saxena } 45592d1d418eSSumit Saxena 45602d1d418eSSumit Saxena if ((data_len_blks >= sc->io_throttle_data_length) && 45612d1d418eSSumit Saxena throttle_enabled_dev) { 45622d1d418eSSumit Saxena mpi3mr_atomic_sub(&sc->pend_large_data_sz, data_len_blks); 45632d1d418eSSumit Saxena ioc_pend_data_len = mpi3mr_atomic_read( 45642d1d418eSSumit Saxena &sc->pend_large_data_sz); 45652d1d418eSSumit Saxena if (tg) { 45662d1d418eSSumit Saxena mpi3mr_atomic_sub(&tg->pend_large_data_sz, 45672d1d418eSSumit Saxena data_len_blks); 45682d1d418eSSumit Saxena tg_pend_data_len = mpi3mr_atomic_read(&tg->pend_large_data_sz); 45692d1d418eSSumit Saxena if (ratelimit % 1000) { 45702d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_IOT, 45712d1d418eSSumit Saxena "large vd_io completion persist_id(%d), handle(0x%04x), data_len(%d)," 45722d1d418eSSumit Saxena "ioc_pending(%d), tg_pending(%d), ioc_low(%d), tg_low(%d)\n", 45732d1d418eSSumit Saxena target->per_id, 45742d1d418eSSumit Saxena target->dev_handle, 45752d1d418eSSumit Saxena data_len_blks, ioc_pend_data_len, 45762d1d418eSSumit Saxena tg_pend_data_len, 45772d1d418eSSumit Saxena sc->io_throttle_low, 45782d1d418eSSumit Saxena tg->low); 45792d1d418eSSumit Saxena ratelimit++; 45802d1d418eSSumit Saxena } 45812d1d418eSSumit Saxena if (tg->io_divert && ((ioc_pend_data_len <= 45822d1d418eSSumit Saxena sc->io_throttle_low) && 45832d1d418eSSumit Saxena (tg_pend_data_len <= tg->low))) { 45842d1d418eSSumit Saxena tg->io_divert = 0; 45852d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_IOT, 45862d1d418eSSumit Saxena "VD: Coming out of divert perst_id(%d) tg_id(%d)\n", 45872d1d418eSSumit Saxena target->per_id, tg->id); 45882d1d418eSSumit Saxena mpi3mr_set_io_divert_for_all_vd_in_tg( 45892d1d418eSSumit Saxena sc, tg, 0); 45902d1d418eSSumit Saxena } 45912d1d418eSSumit Saxena } else { 45922d1d418eSSumit Saxena if (ratelimit % 1000) { 45932d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_IOT, 45942d1d418eSSumit Saxena "large pd_io completion persist_id(%d), handle(0x%04x), data_len(%d), ioc_pending(%d), ioc_low(%d)\n", 45952d1d418eSSumit Saxena target->per_id, 45962d1d418eSSumit Saxena target->dev_handle, 45972d1d418eSSumit Saxena data_len_blks, ioc_pend_data_len, 45982d1d418eSSumit Saxena sc->io_throttle_low); 45992d1d418eSSumit Saxena ratelimit++; 46002d1d418eSSumit Saxena } 46012d1d418eSSumit Saxena 46022d1d418eSSumit Saxena if (ioc_pend_data_len <= sc->io_throttle_low) { 46032d1d418eSSumit Saxena target->io_divert = 0; 46042d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_IOT, 46052d1d418eSSumit Saxena "PD: Coming out of divert perst_id(%d)\n", 46062d1d418eSSumit Saxena target->per_id); 46072d1d418eSSumit Saxena } 46082d1d418eSSumit Saxena } 46092d1d418eSSumit Saxena 46102d1d418eSSumit Saxena } else if (target->io_divert) { 46112d1d418eSSumit Saxena ioc_pend_data_len = mpi3mr_atomic_read(&sc->pend_large_data_sz); 46122d1d418eSSumit Saxena if (!tg) { 46132d1d418eSSumit Saxena if (ratelimit % 1000) { 46142d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_IOT, 46152d1d418eSSumit Saxena "pd_io completion persist_id(%d), handle(0x%04x), data_len(%d), ioc_pending(%d), ioc_low(%d)\n", 46162d1d418eSSumit Saxena target->per_id, 46172d1d418eSSumit Saxena target->dev_handle, 46182d1d418eSSumit Saxena data_len_blks, ioc_pend_data_len, 46192d1d418eSSumit Saxena sc->io_throttle_low); 46202d1d418eSSumit Saxena ratelimit++; 46212d1d418eSSumit Saxena } 46222d1d418eSSumit Saxena 46232d1d418eSSumit Saxena if ( ioc_pend_data_len <= sc->io_throttle_low) { 46242d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_IOT, 46252d1d418eSSumit Saxena "PD: Coming out of divert perst_id(%d)\n", 46262d1d418eSSumit Saxena target->per_id); 46272d1d418eSSumit Saxena target->io_divert = 0; 46282d1d418eSSumit Saxena } 46292d1d418eSSumit Saxena 46302d1d418eSSumit Saxena } else if (ioc_pend_data_len <= sc->io_throttle_low) { 46312d1d418eSSumit Saxena tg_pend_data_len = mpi3mr_atomic_read(&tg->pend_large_data_sz); 46322d1d418eSSumit Saxena if (ratelimit % 1000) { 46332d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_IOT, 46342d1d418eSSumit Saxena "vd_io completion persist_id(%d), handle(0x%04x), data_len(%d)," 46352d1d418eSSumit Saxena "ioc_pending(%d), tg_pending(%d), ioc_low(%d), tg_low(%d)\n", 46362d1d418eSSumit Saxena target->per_id, 46372d1d418eSSumit Saxena target->dev_handle, 46382d1d418eSSumit Saxena data_len_blks, ioc_pend_data_len, 46392d1d418eSSumit Saxena tg_pend_data_len, 46402d1d418eSSumit Saxena sc->io_throttle_low, 46412d1d418eSSumit Saxena tg->low); 46422d1d418eSSumit Saxena ratelimit++; 46432d1d418eSSumit Saxena } 46442d1d418eSSumit Saxena if (tg->io_divert && (tg_pend_data_len <= tg->low)) { 46452d1d418eSSumit Saxena tg->io_divert = 0; 46462d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_IOT, 46472d1d418eSSumit Saxena "VD: Coming out of divert perst_id(%d) tg_id(%d)\n", 46482d1d418eSSumit Saxena target->per_id, tg->id); 46492d1d418eSSumit Saxena mpi3mr_set_io_divert_for_all_vd_in_tg( 46502d1d418eSSumit Saxena sc, tg, 0); 46512d1d418eSSumit Saxena } 46522d1d418eSSumit Saxena 46532d1d418eSSumit Saxena } 46542d1d418eSSumit Saxena } 46552d1d418eSSumit Saxena } 46562d1d418eSSumit Saxena 46572d1d418eSSumit Saxena if (success_desc) { 46582d1d418eSSumit Saxena mpi3mr_set_ccbstatus(ccb, CAM_REQ_CMP); 46592d1d418eSSumit Saxena goto out_success; 46602d1d418eSSumit Saxena } 46612d1d418eSSumit Saxena 46622d1d418eSSumit Saxena if (ioc_status == MPI3_IOCSTATUS_SCSI_DATA_UNDERRUN 46632d1d418eSSumit Saxena && xfer_count == 0 && (scsi_status == MPI3_SCSI_STATUS_BUSY || 46642d1d418eSSumit Saxena scsi_status == MPI3_SCSI_STATUS_RESERVATION_CONFLICT || 46652d1d418eSSumit Saxena scsi_status == MPI3_SCSI_STATUS_TASK_SET_FULL)) 46662d1d418eSSumit Saxena ioc_status = MPI3_IOCSTATUS_SUCCESS; 46672d1d418eSSumit Saxena 46682d1d418eSSumit Saxena if ((sense_state == MPI3_SCSI_STATE_SENSE_VALID) && sense_count 46692d1d418eSSumit Saxena && sense_buf) { 46702d1d418eSSumit Saxena int sense_len, returned_sense_len; 46712d1d418eSSumit Saxena 46722d1d418eSSumit Saxena returned_sense_len = min(le32toh(sense_count), 46732d1d418eSSumit Saxena sizeof(struct scsi_sense_data)); 46742d1d418eSSumit Saxena if (returned_sense_len < csio->sense_len) 46752d1d418eSSumit Saxena csio->sense_resid = csio->sense_len - 46762d1d418eSSumit Saxena returned_sense_len; 46772d1d418eSSumit Saxena else 46782d1d418eSSumit Saxena csio->sense_resid = 0; 46792d1d418eSSumit Saxena 46802d1d418eSSumit Saxena sense_len = min(returned_sense_len, 46812d1d418eSSumit Saxena csio->sense_len - csio->sense_resid); 46822d1d418eSSumit Saxena bzero(&csio->sense_data, sizeof(csio->sense_data)); 46832d1d418eSSumit Saxena bcopy(sense_buf, &csio->sense_data, sense_len); 46842d1d418eSSumit Saxena ccb->ccb_h.status |= CAM_AUTOSNS_VALID; 46852d1d418eSSumit Saxena } 46862d1d418eSSumit Saxena 46872d1d418eSSumit Saxena switch (ioc_status) { 46882d1d418eSSumit Saxena case MPI3_IOCSTATUS_BUSY: 46892d1d418eSSumit Saxena case MPI3_IOCSTATUS_INSUFFICIENT_RESOURCES: 46902d1d418eSSumit Saxena mpi3mr_set_ccbstatus(ccb, CAM_REQUEUE_REQ); 46912d1d418eSSumit Saxena break; 46922d1d418eSSumit Saxena case MPI3_IOCSTATUS_SCSI_DEVICE_NOT_THERE: 46932d1d418eSSumit Saxena /* 46942d1d418eSSumit Saxena * If devinfo is 0 this will be a volume. In that case don't 46952d1d418eSSumit Saxena * tell CAM that the volume is not there. We want volumes to 46962d1d418eSSumit Saxena * be enumerated until they are deleted/removed, not just 46972d1d418eSSumit Saxena * failed. 46982d1d418eSSumit Saxena */ 46992d1d418eSSumit Saxena if (cm->targ->devinfo == 0) 47002d1d418eSSumit Saxena mpi3mr_set_ccbstatus(ccb, CAM_REQ_CMP); 47012d1d418eSSumit Saxena else 47022d1d418eSSumit Saxena mpi3mr_set_ccbstatus(ccb, CAM_DEV_NOT_THERE); 47032d1d418eSSumit Saxena break; 47042d1d418eSSumit Saxena case MPI3_IOCSTATUS_SCSI_TASK_TERMINATED: 47052d1d418eSSumit Saxena case MPI3_IOCSTATUS_SCSI_IOC_TERMINATED: 47062d1d418eSSumit Saxena case MPI3_IOCSTATUS_SCSI_EXT_TERMINATED: 47072d1d418eSSumit Saxena mpi3mr_set_ccbstatus(ccb, CAM_SCSI_BUSY); 47082d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_TRACE, 47092d1d418eSSumit Saxena "func: %s line:%d tgt %u Hosttag %u loginfo %x\n", 47102d1d418eSSumit Saxena __func__, __LINE__, 47112d1d418eSSumit Saxena target_id, cm->hosttag, 47122d1d418eSSumit Saxena le32toh(scsi_reply->IOCLogInfo)); 47132d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_TRACE, 47142d1d418eSSumit Saxena "SCSIStatus %x SCSIState %x xfercount %u\n", 47152d1d418eSSumit Saxena scsi_reply->SCSIStatus, scsi_reply->SCSIState, 47162d1d418eSSumit Saxena le32toh(xfer_count)); 47172d1d418eSSumit Saxena break; 47182d1d418eSSumit Saxena case MPI3_IOCSTATUS_SCSI_DATA_OVERRUN: 47192d1d418eSSumit Saxena /* resid is ignored for this condition */ 47202d1d418eSSumit Saxena csio->resid = 0; 47212d1d418eSSumit Saxena mpi3mr_set_ccbstatus(ccb, CAM_DATA_RUN_ERR); 47222d1d418eSSumit Saxena break; 47232d1d418eSSumit Saxena case MPI3_IOCSTATUS_SCSI_DATA_UNDERRUN: 47242d1d418eSSumit Saxena csio->resid = cm->length - le32toh(xfer_count); 47252d1d418eSSumit Saxena case MPI3_IOCSTATUS_SCSI_RECOVERED_ERROR: 47262d1d418eSSumit Saxena case MPI3_IOCSTATUS_SUCCESS: 4727baabb919SChandrakanth patil if ((scsi_reply->IOCStatus & MPI3_IOCSTATUS_STATUS_MASK) == 47282d1d418eSSumit Saxena MPI3_IOCSTATUS_SCSI_RECOVERED_ERROR) 47292d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_XINFO, "func: %s line: %d recovered error\n", __func__, __LINE__); 47302d1d418eSSumit Saxena 47312d1d418eSSumit Saxena /* Completion failed at the transport level. */ 47322d1d418eSSumit Saxena if (scsi_reply->SCSIState & (MPI3_SCSI_STATE_NO_SCSI_STATUS | 47332d1d418eSSumit Saxena MPI3_SCSI_STATE_TERMINATED)) { 47342d1d418eSSumit Saxena mpi3mr_set_ccbstatus(ccb, CAM_REQ_CMP_ERR); 47352d1d418eSSumit Saxena break; 47362d1d418eSSumit Saxena } 47372d1d418eSSumit Saxena 47382d1d418eSSumit Saxena /* In a modern packetized environment, an autosense failure 47392d1d418eSSumit Saxena * implies that there's not much else that can be done to 47402d1d418eSSumit Saxena * recover the command. 47412d1d418eSSumit Saxena */ 47422d1d418eSSumit Saxena if (scsi_reply->SCSIState & MPI3_SCSI_STATE_SENSE_VALID) { 47432d1d418eSSumit Saxena mpi3mr_set_ccbstatus(ccb, CAM_AUTOSENSE_FAIL); 47442d1d418eSSumit Saxena break; 47452d1d418eSSumit Saxena } 47462d1d418eSSumit Saxena 47472d1d418eSSumit Saxena /* 47482d1d418eSSumit Saxena * Intentionally override the normal SCSI status reporting 47492d1d418eSSumit Saxena * for these two cases. These are likely to happen in a 47502d1d418eSSumit Saxena * multi-initiator environment, and we want to make sure that 47512d1d418eSSumit Saxena * CAM retries these commands rather than fail them. 47522d1d418eSSumit Saxena */ 47532d1d418eSSumit Saxena if ((scsi_reply->SCSIStatus == MPI3_SCSI_STATUS_COMMAND_TERMINATED) || 47542d1d418eSSumit Saxena (scsi_reply->SCSIStatus == MPI3_SCSI_STATUS_TASK_ABORTED)) { 47552d1d418eSSumit Saxena mpi3mr_set_ccbstatus(ccb, CAM_REQ_ABORTED); 47562d1d418eSSumit Saxena break; 47572d1d418eSSumit Saxena } 47582d1d418eSSumit Saxena 47592d1d418eSSumit Saxena /* Handle normal status and sense */ 47602d1d418eSSumit Saxena csio->scsi_status = scsi_reply->SCSIStatus; 47612d1d418eSSumit Saxena if (scsi_reply->SCSIStatus == MPI3_SCSI_STATUS_GOOD) 47622d1d418eSSumit Saxena mpi3mr_set_ccbstatus(ccb, CAM_REQ_CMP); 47632d1d418eSSumit Saxena else 47642d1d418eSSumit Saxena mpi3mr_set_ccbstatus(ccb, CAM_SCSI_STATUS_ERROR); 47652d1d418eSSumit Saxena 47662d1d418eSSumit Saxena if (scsi_reply->SCSIState & MPI3_SCSI_STATE_SENSE_VALID) { 47672d1d418eSSumit Saxena int sense_len, returned_sense_len; 47682d1d418eSSumit Saxena 47692d1d418eSSumit Saxena returned_sense_len = min(le32toh(scsi_reply->SenseCount), 47702d1d418eSSumit Saxena sizeof(struct scsi_sense_data)); 47712d1d418eSSumit Saxena if (returned_sense_len < csio->sense_len) 47722d1d418eSSumit Saxena csio->sense_resid = csio->sense_len - 47732d1d418eSSumit Saxena returned_sense_len; 47742d1d418eSSumit Saxena else 47752d1d418eSSumit Saxena csio->sense_resid = 0; 47762d1d418eSSumit Saxena 47772d1d418eSSumit Saxena sense_len = min(returned_sense_len, 47782d1d418eSSumit Saxena csio->sense_len - csio->sense_resid); 47792d1d418eSSumit Saxena bzero(&csio->sense_data, sizeof(csio->sense_data)); 47802d1d418eSSumit Saxena bcopy(cm->sense, &csio->sense_data, sense_len); 47812d1d418eSSumit Saxena ccb->ccb_h.status |= CAM_AUTOSNS_VALID; 47822d1d418eSSumit Saxena } 47832d1d418eSSumit Saxena 47842d1d418eSSumit Saxena break; 47852d1d418eSSumit Saxena case MPI3_IOCSTATUS_INVALID_SGL: 47862d1d418eSSumit Saxena mpi3mr_set_ccbstatus(ccb, CAM_UNREC_HBA_ERROR); 47872d1d418eSSumit Saxena break; 47882d1d418eSSumit Saxena case MPI3_IOCSTATUS_EEDP_GUARD_ERROR: 47892d1d418eSSumit Saxena case MPI3_IOCSTATUS_EEDP_REF_TAG_ERROR: 47902d1d418eSSumit Saxena case MPI3_IOCSTATUS_EEDP_APP_TAG_ERROR: 47912d1d418eSSumit Saxena case MPI3_IOCSTATUS_SCSI_PROTOCOL_ERROR: 47922d1d418eSSumit Saxena case MPI3_IOCSTATUS_INVALID_FUNCTION: 47932d1d418eSSumit Saxena case MPI3_IOCSTATUS_INTERNAL_ERROR: 47942d1d418eSSumit Saxena case MPI3_IOCSTATUS_INVALID_FIELD: 47952d1d418eSSumit Saxena case MPI3_IOCSTATUS_INVALID_STATE: 47962d1d418eSSumit Saxena case MPI3_IOCSTATUS_SCSI_IO_DATA_ERROR: 47972d1d418eSSumit Saxena case MPI3_IOCSTATUS_SCSI_TASK_MGMT_FAILED: 47982d1d418eSSumit Saxena case MPI3_IOCSTATUS_INSUFFICIENT_POWER: 47992d1d418eSSumit Saxena case MPI3_IOCSTATUS_SCSI_RESIDUAL_MISMATCH: 48002d1d418eSSumit Saxena default: 48012d1d418eSSumit Saxena csio->resid = cm->length; 48022d1d418eSSumit Saxena mpi3mr_set_ccbstatus(ccb, CAM_REQ_CMP_ERR); 48032d1d418eSSumit Saxena break; 48042d1d418eSSumit Saxena } 48052d1d418eSSumit Saxena 48062d1d418eSSumit Saxena out_success: 48072d1d418eSSumit Saxena if (mpi3mr_get_ccbstatus(ccb) != CAM_REQ_CMP) { 48082d1d418eSSumit Saxena ccb->ccb_h.status |= CAM_DEV_QFRZN; 48092d1d418eSSumit Saxena xpt_freeze_devq(ccb->ccb_h.path, /*count*/ 1); 48102d1d418eSSumit Saxena } 48112d1d418eSSumit Saxena 48122d1d418eSSumit Saxena mpi3mr_atomic_dec(&cm->targ->outstanding); 48132d1d418eSSumit Saxena mpi3mr_cmd_done(sc, cm); 48142d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_TRACE, "Completion IO path :" 48152d1d418eSSumit Saxena " cdb[0]: %x targetid: 0x%x SMID: %x ioc_status: 0x%x ioc_loginfo: 0x%x scsi_status: 0x%x " 48162d1d418eSSumit Saxena "scsi_state: 0x%x response_data: 0x%x\n", scsi_cdb[0], target_id, host_tag, 48172d1d418eSSumit Saxena ioc_status, ioc_loginfo, scsi_status, scsi_state, resp_data); 48182d1d418eSSumit Saxena mpi3mr_atomic_dec(&sc->fw_outstanding); 48192d1d418eSSumit Saxena out: 48202d1d418eSSumit Saxena 48212d1d418eSSumit Saxena if (sense_buf) 48222d1d418eSSumit Saxena mpi3mr_repost_sense_buf(sc, 48232d1d418eSSumit Saxena scsi_reply->SenseDataBufferAddress); 48242d1d418eSSumit Saxena return; 48252d1d418eSSumit Saxena } 48262d1d418eSSumit Saxena 48272d1d418eSSumit Saxena /* 48282d1d418eSSumit Saxena * mpi3mr_complete_io_cmd: ISR routine for IO commands 48292d1d418eSSumit Saxena * @sc: Adapter's soft instance 48302d1d418eSSumit Saxena * @irq_ctx: Driver's internal per IRQ structure 48312d1d418eSSumit Saxena * 48322d1d418eSSumit Saxena * This function processes IO command completions. 48332d1d418eSSumit Saxena */ 48342d1d418eSSumit Saxena int mpi3mr_complete_io_cmd(struct mpi3mr_softc *sc, 48352d1d418eSSumit Saxena struct mpi3mr_irq_context *irq_ctx) 48362d1d418eSSumit Saxena { 48372d1d418eSSumit Saxena struct mpi3mr_op_reply_queue *op_reply_q = irq_ctx->op_reply_q; 48382d1d418eSSumit Saxena U32 exp_phase = op_reply_q->ephase; 48392d1d418eSSumit Saxena U32 reply_ci = op_reply_q->ci; 48402d1d418eSSumit Saxena U32 num_op_replies = 0; 48412d1d418eSSumit Saxena U64 reply_dma = 0; 48422d1d418eSSumit Saxena Mpi3DefaultReplyDescriptor_t *reply_desc; 4843eb7a4b35SChandrakanth patil U16 req_qid = 0, threshold_comps = 0; 48442d1d418eSSumit Saxena 48452d1d418eSSumit Saxena mtx_lock_spin(&op_reply_q->q_lock); 48462d1d418eSSumit Saxena if (op_reply_q->in_use == false) { 48472d1d418eSSumit Saxena op_reply_q->in_use = true; 48482d1d418eSSumit Saxena mtx_unlock_spin(&op_reply_q->q_lock); 48492d1d418eSSumit Saxena } else { 48502d1d418eSSumit Saxena mtx_unlock_spin(&op_reply_q->q_lock); 48512d1d418eSSumit Saxena return 0; 48522d1d418eSSumit Saxena } 48532d1d418eSSumit Saxena 48542d1d418eSSumit Saxena reply_desc = (Mpi3DefaultReplyDescriptor_t *)op_reply_q->q_base + reply_ci; 48552d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_TRACE, "[QID:%d]:reply_desc: (%pa) reply_ci: %x" 48562d1d418eSSumit Saxena " reply_desc->ReplyFlags: 0x%x\n" 48572d1d418eSSumit Saxena "reply_q_base_phys: %#016jx reply_q_base: (%pa) exp_phase: %x\n", 48582d1d418eSSumit Saxena op_reply_q->qid, reply_desc, reply_ci, reply_desc->ReplyFlags, op_reply_q->q_base_phys, 48592d1d418eSSumit Saxena op_reply_q->q_base, exp_phase); 48602d1d418eSSumit Saxena 48612d1d418eSSumit Saxena if (((reply_desc->ReplyFlags & 48622d1d418eSSumit Saxena MPI3_REPLY_DESCRIPT_FLAGS_PHASE_MASK) != exp_phase) || !op_reply_q->qid) { 48632d1d418eSSumit Saxena mtx_lock_spin(&op_reply_q->q_lock); 48642d1d418eSSumit Saxena op_reply_q->in_use = false; 48652d1d418eSSumit Saxena mtx_unlock_spin(&op_reply_q->q_lock); 48662d1d418eSSumit Saxena return 0; 48672d1d418eSSumit Saxena } 48682d1d418eSSumit Saxena 48692d1d418eSSumit Saxena do { 48702d1d418eSSumit Saxena req_qid = reply_desc->RequestQueueID; 48712d1d418eSSumit Saxena sc->op_req_q[req_qid - 1].ci = 48722d1d418eSSumit Saxena reply_desc->RequestQueueCI; 48732d1d418eSSumit Saxena 48742d1d418eSSumit Saxena mpi3mr_process_op_reply_desc(sc, reply_desc, &reply_dma); 48752d1d418eSSumit Saxena mpi3mr_atomic_dec(&op_reply_q->pend_ios); 48762d1d418eSSumit Saxena if (reply_dma) 48772d1d418eSSumit Saxena mpi3mr_repost_reply_buf(sc, reply_dma); 48782d1d418eSSumit Saxena num_op_replies++; 48792d1d418eSSumit Saxena if (++reply_ci == op_reply_q->num_replies) { 48802d1d418eSSumit Saxena reply_ci = 0; 48812d1d418eSSumit Saxena exp_phase ^= 1; 48822d1d418eSSumit Saxena } 48832d1d418eSSumit Saxena reply_desc = 48842d1d418eSSumit Saxena (Mpi3DefaultReplyDescriptor_t *)op_reply_q->q_base + reply_ci; 48852d1d418eSSumit Saxena if ((reply_desc->ReplyFlags & 48862d1d418eSSumit Saxena MPI3_REPLY_DESCRIPT_FLAGS_PHASE_MASK) != exp_phase) 48872d1d418eSSumit Saxena break; 4888eb7a4b35SChandrakanth patil 4889eb7a4b35SChandrakanth patil if (++threshold_comps == MPI3MR_THRESHOLD_REPLY_COUNT) { 4890eb7a4b35SChandrakanth patil mpi3mr_regwrite(sc, MPI3_SYSIF_OPER_REPLY_Q_N_CI_OFFSET(op_reply_q->qid), reply_ci); 4891eb7a4b35SChandrakanth patil threshold_comps = 0; 4892eb7a4b35SChandrakanth patil } 4893eb7a4b35SChandrakanth patil 48942d1d418eSSumit Saxena } while (1); 48952d1d418eSSumit Saxena 48962d1d418eSSumit Saxena 48972d1d418eSSumit Saxena mpi3mr_regwrite(sc, MPI3_SYSIF_OPER_REPLY_Q_N_CI_OFFSET(op_reply_q->qid), reply_ci); 48982d1d418eSSumit Saxena op_reply_q->ci = reply_ci; 48992d1d418eSSumit Saxena op_reply_q->ephase = exp_phase; 49002d1d418eSSumit Saxena mtx_lock_spin(&op_reply_q->q_lock); 49012d1d418eSSumit Saxena op_reply_q->in_use = false; 49022d1d418eSSumit Saxena mtx_unlock_spin(&op_reply_q->q_lock); 49032d1d418eSSumit Saxena return num_op_replies; 49042d1d418eSSumit Saxena } 49052d1d418eSSumit Saxena 49062d1d418eSSumit Saxena /* 49072d1d418eSSumit Saxena * mpi3mr_isr: Primary ISR function 49082d1d418eSSumit Saxena * privdata: Driver's internal per IRQ structure 49092d1d418eSSumit Saxena * 49102d1d418eSSumit Saxena * This is driver's primary ISR function which is being called whenever any admin/IO 49112d1d418eSSumit Saxena * command completion. 49122d1d418eSSumit Saxena */ 49132d1d418eSSumit Saxena void mpi3mr_isr(void *privdata) 49142d1d418eSSumit Saxena { 49152d1d418eSSumit Saxena struct mpi3mr_irq_context *irq_ctx = (struct mpi3mr_irq_context *)privdata; 49162d1d418eSSumit Saxena struct mpi3mr_softc *sc = irq_ctx->sc; 49172d1d418eSSumit Saxena U16 msi_idx; 49182d1d418eSSumit Saxena 49192d1d418eSSumit Saxena if (!irq_ctx) 49202d1d418eSSumit Saxena return; 49212d1d418eSSumit Saxena 49222d1d418eSSumit Saxena msi_idx = irq_ctx->msix_index; 49232d1d418eSSumit Saxena 49242d1d418eSSumit Saxena if (!sc->intr_enabled) 49252d1d418eSSumit Saxena return; 49262d1d418eSSumit Saxena 49272d1d418eSSumit Saxena if (!msi_idx) 49282d1d418eSSumit Saxena mpi3mr_complete_admin_cmd(sc); 49292d1d418eSSumit Saxena 49302d1d418eSSumit Saxena if (irq_ctx->op_reply_q && irq_ctx->op_reply_q->qid) { 49312d1d418eSSumit Saxena mpi3mr_complete_io_cmd(sc, irq_ctx); 49322d1d418eSSumit Saxena } 49332d1d418eSSumit Saxena } 49342d1d418eSSumit Saxena 49352d1d418eSSumit Saxena /* 49362d1d418eSSumit Saxena * mpi3mr_alloc_requests - Allocates host commands 49372d1d418eSSumit Saxena * @sc: Adapter reference 49382d1d418eSSumit Saxena * 49392d1d418eSSumit Saxena * This function allocates controller supported host commands 49402d1d418eSSumit Saxena * 49412d1d418eSSumit Saxena * Return: 0 on success and proper error codes on failure 49422d1d418eSSumit Saxena */ 49432d1d418eSSumit Saxena int 49442d1d418eSSumit Saxena mpi3mr_alloc_requests(struct mpi3mr_softc *sc) 49452d1d418eSSumit Saxena { 49462d1d418eSSumit Saxena struct mpi3mr_cmd *cmd; 49472d1d418eSSumit Saxena int i, j, nsegs, ret; 49482d1d418eSSumit Saxena 49492d1d418eSSumit Saxena nsegs = MPI3MR_SG_DEPTH; 49502d1d418eSSumit Saxena ret = bus_dma_tag_create( sc->mpi3mr_parent_dmat, /* parent */ 49512d1d418eSSumit Saxena 1, 0, /* algnmnt, boundary */ 4952ee7c431cSWarner Losh sc->dma_loaddr, /* lowaddr */ 49531ec7c672SWarner Losh BUS_SPACE_MAXADDR, /* highaddr */ 49542d1d418eSSumit Saxena NULL, NULL, /* filter, filterarg */ 49554e6d128bSAlexander Motin BUS_SPACE_MAXSIZE, /* maxsize */ 49562d1d418eSSumit Saxena nsegs, /* nsegments */ 49574e6d128bSAlexander Motin BUS_SPACE_MAXSIZE_32BIT,/* maxsegsize */ 49582d1d418eSSumit Saxena BUS_DMA_ALLOCNOW, /* flags */ 49592d1d418eSSumit Saxena busdma_lock_mutex, /* lockfunc */ 49602d1d418eSSumit Saxena &sc->io_lock, /* lockarg */ 49612d1d418eSSumit Saxena &sc->buffer_dmat); 49622d1d418eSSumit Saxena if (ret) { 49632d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_ERROR, "Cannot allocate buffer DMA tag ret: %d\n", ret); 49642d1d418eSSumit Saxena return (ENOMEM); 49652d1d418eSSumit Saxena } 49662d1d418eSSumit Saxena 49672d1d418eSSumit Saxena /* 49682d1d418eSSumit Saxena * sc->cmd_list is an array of struct mpi3mr_cmd pointers. 49692d1d418eSSumit Saxena * Allocate the dynamic array first and then allocate individual 49702d1d418eSSumit Saxena * commands. 49712d1d418eSSumit Saxena */ 49722d1d418eSSumit Saxena sc->cmd_list = malloc(sizeof(struct mpi3mr_cmd *) * sc->max_host_ios, 49732d1d418eSSumit Saxena M_MPI3MR, M_NOWAIT | M_ZERO); 49742d1d418eSSumit Saxena 49752d1d418eSSumit Saxena if (!sc->cmd_list) { 49762d1d418eSSumit Saxena device_printf(sc->mpi3mr_dev, "Cannot alloc memory for mpt_cmd_list.\n"); 49772d1d418eSSumit Saxena return (ENOMEM); 49782d1d418eSSumit Saxena } 49792d1d418eSSumit Saxena 49802d1d418eSSumit Saxena for (i = 0; i < sc->max_host_ios; i++) { 49812d1d418eSSumit Saxena sc->cmd_list[i] = malloc(sizeof(struct mpi3mr_cmd), 49822d1d418eSSumit Saxena M_MPI3MR, M_NOWAIT | M_ZERO); 49832d1d418eSSumit Saxena if (!sc->cmd_list[i]) { 49842d1d418eSSumit Saxena for (j = 0; j < i; j++) 49852d1d418eSSumit Saxena free(sc->cmd_list[j], M_MPI3MR); 49862d1d418eSSumit Saxena free(sc->cmd_list, M_MPI3MR); 49872d1d418eSSumit Saxena sc->cmd_list = NULL; 49882d1d418eSSumit Saxena return (ENOMEM); 49892d1d418eSSumit Saxena } 49902d1d418eSSumit Saxena } 49912d1d418eSSumit Saxena 49922d1d418eSSumit Saxena for (i = 1; i < sc->max_host_ios; i++) { 49932d1d418eSSumit Saxena cmd = sc->cmd_list[i]; 49942d1d418eSSumit Saxena cmd->hosttag = i; 49952d1d418eSSumit Saxena cmd->sc = sc; 49962d1d418eSSumit Saxena cmd->state = MPI3MR_CMD_STATE_BUSY; 49972d1d418eSSumit Saxena callout_init_mtx(&cmd->callout, &sc->mpi3mr_mtx, 0); 49982d1d418eSSumit Saxena cmd->ccb = NULL; 49992d1d418eSSumit Saxena TAILQ_INSERT_TAIL(&(sc->cmd_list_head), cmd, next); 50002d1d418eSSumit Saxena if (bus_dmamap_create(sc->buffer_dmat, 0, &cmd->dmamap)) 50012d1d418eSSumit Saxena return ENOMEM; 50022d1d418eSSumit Saxena } 50032d1d418eSSumit Saxena return (0); 50042d1d418eSSumit Saxena } 50052d1d418eSSumit Saxena 50062d1d418eSSumit Saxena /* 50072d1d418eSSumit Saxena * mpi3mr_get_command: Get a coomand structure from free command pool 50082d1d418eSSumit Saxena * @sc: Adapter soft instance 50092d1d418eSSumit Saxena * Return: MPT command reference 50102d1d418eSSumit Saxena * 50112d1d418eSSumit Saxena * This function returns an MPT command to the caller. 50122d1d418eSSumit Saxena */ 50132d1d418eSSumit Saxena struct mpi3mr_cmd * 50142d1d418eSSumit Saxena mpi3mr_get_command(struct mpi3mr_softc *sc) 50152d1d418eSSumit Saxena { 50162d1d418eSSumit Saxena struct mpi3mr_cmd *cmd = NULL; 50172d1d418eSSumit Saxena 50182d1d418eSSumit Saxena mtx_lock(&sc->cmd_pool_lock); 50192d1d418eSSumit Saxena if (!TAILQ_EMPTY(&sc->cmd_list_head)) { 50202d1d418eSSumit Saxena cmd = TAILQ_FIRST(&sc->cmd_list_head); 50212d1d418eSSumit Saxena TAILQ_REMOVE(&sc->cmd_list_head, cmd, next); 50222d1d418eSSumit Saxena } else { 50232d1d418eSSumit Saxena goto out; 50242d1d418eSSumit Saxena } 50252d1d418eSSumit Saxena 50262d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_TRACE, "Get command SMID: 0x%x\n", cmd->hosttag); 50272d1d418eSSumit Saxena 50282d1d418eSSumit Saxena memset((uint8_t *)&cmd->io_request, 0, MPI3MR_AREQ_FRAME_SZ); 50292d1d418eSSumit Saxena cmd->data_dir = 0; 50302d1d418eSSumit Saxena cmd->ccb = NULL; 50312d1d418eSSumit Saxena cmd->targ = NULL; 50322d1d418eSSumit Saxena cmd->state = MPI3MR_CMD_STATE_BUSY; 50332d1d418eSSumit Saxena cmd->data = NULL; 50342d1d418eSSumit Saxena cmd->length = 0; 50352d1d418eSSumit Saxena out: 50362d1d418eSSumit Saxena mtx_unlock(&sc->cmd_pool_lock); 50372d1d418eSSumit Saxena return cmd; 50382d1d418eSSumit Saxena } 50392d1d418eSSumit Saxena 50402d1d418eSSumit Saxena /* 50412d1d418eSSumit Saxena * mpi3mr_release_command: Return a cmd to free command pool 50422d1d418eSSumit Saxena * input: Command packet for return to free command pool 50432d1d418eSSumit Saxena * 50442d1d418eSSumit Saxena * This function returns an MPT command to the free command list. 50452d1d418eSSumit Saxena */ 50462d1d418eSSumit Saxena void 50472d1d418eSSumit Saxena mpi3mr_release_command(struct mpi3mr_cmd *cmd) 50482d1d418eSSumit Saxena { 50492d1d418eSSumit Saxena struct mpi3mr_softc *sc = cmd->sc; 50502d1d418eSSumit Saxena 50512d1d418eSSumit Saxena mtx_lock(&sc->cmd_pool_lock); 50522d1d418eSSumit Saxena TAILQ_INSERT_HEAD(&(sc->cmd_list_head), cmd, next); 50532d1d418eSSumit Saxena cmd->state = MPI3MR_CMD_STATE_FREE; 50542d1d418eSSumit Saxena cmd->req_qidx = 0; 50552d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_TRACE, "Release command SMID: 0x%x\n", cmd->hosttag); 50562d1d418eSSumit Saxena mtx_unlock(&sc->cmd_pool_lock); 50572d1d418eSSumit Saxena 50582d1d418eSSumit Saxena return; 50592d1d418eSSumit Saxena } 50602d1d418eSSumit Saxena 50612d1d418eSSumit Saxena /** 50622d1d418eSSumit Saxena * mpi3mr_free_ioctl_dma_memory - free memory for ioctl dma 50632d1d418eSSumit Saxena * @sc: Adapter instance reference 50642d1d418eSSumit Saxena * 50652d1d418eSSumit Saxena * Free the DMA memory allocated for IOCTL handling purpose. 50662d1d418eSSumit Saxena * 50672d1d418eSSumit Saxena * Return: None 50682d1d418eSSumit Saxena */ 50692d1d418eSSumit Saxena static void mpi3mr_free_ioctl_dma_memory(struct mpi3mr_softc *sc) 50702d1d418eSSumit Saxena { 50712d1d418eSSumit Saxena U16 i; 50722d1d418eSSumit Saxena struct dma_memory_desc *mem_desc; 50732d1d418eSSumit Saxena 50742d1d418eSSumit Saxena for (i=0; i<MPI3MR_NUM_IOCTL_SGE; i++) { 50752d1d418eSSumit Saxena mem_desc = &sc->ioctl_sge[i]; 50762d1d418eSSumit Saxena if (mem_desc->addr && mem_desc->dma_addr) { 50772d1d418eSSumit Saxena bus_dmamap_unload(mem_desc->tag, mem_desc->dmamap); 50782d1d418eSSumit Saxena bus_dmamem_free(mem_desc->tag, mem_desc->addr, mem_desc->dmamap); 50792d1d418eSSumit Saxena mem_desc->addr = NULL; 50802d1d418eSSumit Saxena if (mem_desc->tag != NULL) 50812d1d418eSSumit Saxena bus_dma_tag_destroy(mem_desc->tag); 50822d1d418eSSumit Saxena } 50832d1d418eSSumit Saxena } 50842d1d418eSSumit Saxena 50852d1d418eSSumit Saxena mem_desc = &sc->ioctl_chain_sge; 50862d1d418eSSumit Saxena if (mem_desc->addr && mem_desc->dma_addr) { 50872d1d418eSSumit Saxena bus_dmamap_unload(mem_desc->tag, mem_desc->dmamap); 50882d1d418eSSumit Saxena bus_dmamem_free(mem_desc->tag, mem_desc->addr, mem_desc->dmamap); 50892d1d418eSSumit Saxena mem_desc->addr = NULL; 50902d1d418eSSumit Saxena if (mem_desc->tag != NULL) 50912d1d418eSSumit Saxena bus_dma_tag_destroy(mem_desc->tag); 50922d1d418eSSumit Saxena } 50932d1d418eSSumit Saxena 50942d1d418eSSumit Saxena mem_desc = &sc->ioctl_resp_sge; 50952d1d418eSSumit Saxena if (mem_desc->addr && mem_desc->dma_addr) { 50962d1d418eSSumit Saxena bus_dmamap_unload(mem_desc->tag, mem_desc->dmamap); 50972d1d418eSSumit Saxena bus_dmamem_free(mem_desc->tag, mem_desc->addr, mem_desc->dmamap); 50982d1d418eSSumit Saxena mem_desc->addr = NULL; 50992d1d418eSSumit Saxena if (mem_desc->tag != NULL) 51002d1d418eSSumit Saxena bus_dma_tag_destroy(mem_desc->tag); 51012d1d418eSSumit Saxena } 51022d1d418eSSumit Saxena 51032d1d418eSSumit Saxena sc->ioctl_sges_allocated = false; 51042d1d418eSSumit Saxena } 51052d1d418eSSumit Saxena 51062d1d418eSSumit Saxena /** 51072d1d418eSSumit Saxena * mpi3mr_alloc_ioctl_dma_memory - Alloc memory for ioctl dma 51082d1d418eSSumit Saxena * @sc: Adapter instance reference 51092d1d418eSSumit Saxena * 51102d1d418eSSumit Saxena * This function allocates dmaable memory required to handle the 51112d1d418eSSumit Saxena * application issued MPI3 IOCTL requests. 51122d1d418eSSumit Saxena * 51132d1d418eSSumit Saxena * Return: None 51142d1d418eSSumit Saxena */ 51152d1d418eSSumit Saxena void mpi3mr_alloc_ioctl_dma_memory(struct mpi3mr_softc *sc) 51162d1d418eSSumit Saxena { 51172d1d418eSSumit Saxena struct dma_memory_desc *mem_desc; 51182d1d418eSSumit Saxena U16 i; 51192d1d418eSSumit Saxena 51202d1d418eSSumit Saxena for (i=0; i<MPI3MR_NUM_IOCTL_SGE; i++) { 51212d1d418eSSumit Saxena mem_desc = &sc->ioctl_sge[i]; 51222d1d418eSSumit Saxena mem_desc->size = MPI3MR_IOCTL_SGE_SIZE; 51232d1d418eSSumit Saxena 51242d1d418eSSumit Saxena if (bus_dma_tag_create(sc->mpi3mr_parent_dmat, /* parent */ 51252d1d418eSSumit Saxena 4, 0, /* algnmnt, boundary */ 5126ee7c431cSWarner Losh sc->dma_loaddr, /* lowaddr */ 51271ec7c672SWarner Losh BUS_SPACE_MAXADDR, /* highaddr */ 51282d1d418eSSumit Saxena NULL, NULL, /* filter, filterarg */ 51292d1d418eSSumit Saxena mem_desc->size, /* maxsize */ 51302d1d418eSSumit Saxena 1, /* nsegments */ 51312d1d418eSSumit Saxena mem_desc->size, /* maxsegsize */ 51322d1d418eSSumit Saxena 0, /* flags */ 51332d1d418eSSumit Saxena NULL, NULL, /* lockfunc, lockarg */ 51342d1d418eSSumit Saxena &mem_desc->tag)) { 51352d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_ERROR, "Cannot allocate request DMA tag\n"); 51362d1d418eSSumit Saxena goto out_failed; 51372d1d418eSSumit Saxena } 51382d1d418eSSumit Saxena 51392d1d418eSSumit Saxena if (bus_dmamem_alloc(mem_desc->tag, (void **)&mem_desc->addr, 51402d1d418eSSumit Saxena BUS_DMA_NOWAIT, &mem_desc->dmamap)) { 5141ee7c431cSWarner Losh mpi3mr_dprint(sc, MPI3MR_ERROR, "%s: Cannot allocate replies memory\n", __func__); 51422d1d418eSSumit Saxena goto out_failed; 51432d1d418eSSumit Saxena } 51442d1d418eSSumit Saxena bzero(mem_desc->addr, mem_desc->size); 51452d1d418eSSumit Saxena bus_dmamap_load(mem_desc->tag, mem_desc->dmamap, mem_desc->addr, mem_desc->size, 514639a3e6a8SAlexander Motin mpi3mr_memaddr_cb, &mem_desc->dma_addr, BUS_DMA_NOWAIT); 51472d1d418eSSumit Saxena 51482d1d418eSSumit Saxena if (!mem_desc->addr) 51492d1d418eSSumit Saxena goto out_failed; 51502d1d418eSSumit Saxena } 51512d1d418eSSumit Saxena 51522d1d418eSSumit Saxena mem_desc = &sc->ioctl_chain_sge; 51532d1d418eSSumit Saxena mem_desc->size = MPI3MR_4K_PGSZ; 51542d1d418eSSumit Saxena if (bus_dma_tag_create(sc->mpi3mr_parent_dmat, /* parent */ 51552d1d418eSSumit Saxena 4, 0, /* algnmnt, boundary */ 5156ee7c431cSWarner Losh sc->dma_loaddr, /* lowaddr */ 51571ec7c672SWarner Losh BUS_SPACE_MAXADDR, /* highaddr */ 51582d1d418eSSumit Saxena NULL, NULL, /* filter, filterarg */ 51592d1d418eSSumit Saxena mem_desc->size, /* maxsize */ 51602d1d418eSSumit Saxena 1, /* nsegments */ 51612d1d418eSSumit Saxena mem_desc->size, /* maxsegsize */ 51622d1d418eSSumit Saxena 0, /* flags */ 51632d1d418eSSumit Saxena NULL, NULL, /* lockfunc, lockarg */ 51642d1d418eSSumit Saxena &mem_desc->tag)) { 51652d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_ERROR, "Cannot allocate request DMA tag\n"); 51662d1d418eSSumit Saxena goto out_failed; 51672d1d418eSSumit Saxena } 51682d1d418eSSumit Saxena 51692d1d418eSSumit Saxena if (bus_dmamem_alloc(mem_desc->tag, (void **)&mem_desc->addr, 51702d1d418eSSumit Saxena BUS_DMA_NOWAIT, &mem_desc->dmamap)) { 5171ee7c431cSWarner Losh mpi3mr_dprint(sc, MPI3MR_ERROR, "%s: Cannot allocate replies memory\n", __func__); 51722d1d418eSSumit Saxena goto out_failed; 51732d1d418eSSumit Saxena } 51742d1d418eSSumit Saxena bzero(mem_desc->addr, mem_desc->size); 51752d1d418eSSumit Saxena bus_dmamap_load(mem_desc->tag, mem_desc->dmamap, mem_desc->addr, mem_desc->size, 517639a3e6a8SAlexander Motin mpi3mr_memaddr_cb, &mem_desc->dma_addr, BUS_DMA_NOWAIT); 51772d1d418eSSumit Saxena 51782d1d418eSSumit Saxena if (!mem_desc->addr) 51792d1d418eSSumit Saxena goto out_failed; 51802d1d418eSSumit Saxena 51812d1d418eSSumit Saxena mem_desc = &sc->ioctl_resp_sge; 51822d1d418eSSumit Saxena mem_desc->size = MPI3MR_4K_PGSZ; 51832d1d418eSSumit Saxena if (bus_dma_tag_create(sc->mpi3mr_parent_dmat, /* parent */ 51842d1d418eSSumit Saxena 4, 0, /* algnmnt, boundary */ 5185ee7c431cSWarner Losh sc->dma_loaddr, /* lowaddr */ 51861ec7c672SWarner Losh BUS_SPACE_MAXADDR, /* highaddr */ 51872d1d418eSSumit Saxena NULL, NULL, /* filter, filterarg */ 51882d1d418eSSumit Saxena mem_desc->size, /* maxsize */ 51892d1d418eSSumit Saxena 1, /* nsegments */ 51902d1d418eSSumit Saxena mem_desc->size, /* maxsegsize */ 51912d1d418eSSumit Saxena 0, /* flags */ 51922d1d418eSSumit Saxena NULL, NULL, /* lockfunc, lockarg */ 51932d1d418eSSumit Saxena &mem_desc->tag)) { 51942d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_ERROR, "Cannot allocate request DMA tag\n"); 51952d1d418eSSumit Saxena goto out_failed; 51962d1d418eSSumit Saxena } 51972d1d418eSSumit Saxena 51982d1d418eSSumit Saxena if (bus_dmamem_alloc(mem_desc->tag, (void **)&mem_desc->addr, 51992d1d418eSSumit Saxena BUS_DMA_NOWAIT, &mem_desc->dmamap)) { 52002d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_ERROR, "Cannot allocate replies memory\n"); 52012d1d418eSSumit Saxena goto out_failed; 52022d1d418eSSumit Saxena } 52032d1d418eSSumit Saxena bzero(mem_desc->addr, mem_desc->size); 52042d1d418eSSumit Saxena bus_dmamap_load(mem_desc->tag, mem_desc->dmamap, mem_desc->addr, mem_desc->size, 520539a3e6a8SAlexander Motin mpi3mr_memaddr_cb, &mem_desc->dma_addr, BUS_DMA_NOWAIT); 52062d1d418eSSumit Saxena 52072d1d418eSSumit Saxena if (!mem_desc->addr) 52082d1d418eSSumit Saxena goto out_failed; 52092d1d418eSSumit Saxena 52102d1d418eSSumit Saxena sc->ioctl_sges_allocated = true; 52112d1d418eSSumit Saxena 52122d1d418eSSumit Saxena return; 52132d1d418eSSumit Saxena out_failed: 52142d1d418eSSumit Saxena printf("cannot allocate DMA memory for the mpt commands" 52152d1d418eSSumit Saxena " from the applications, application interface for MPT command is disabled\n"); 52162d1d418eSSumit Saxena mpi3mr_free_ioctl_dma_memory(sc); 52172d1d418eSSumit Saxena } 52182d1d418eSSumit Saxena 52192d1d418eSSumit Saxena void 52202d1d418eSSumit Saxena mpi3mr_destory_mtx(struct mpi3mr_softc *sc) 52212d1d418eSSumit Saxena { 52222d1d418eSSumit Saxena int i; 52232d1d418eSSumit Saxena struct mpi3mr_op_req_queue *op_req_q; 52242d1d418eSSumit Saxena struct mpi3mr_op_reply_queue *op_reply_q; 52252d1d418eSSumit Saxena 52262d1d418eSSumit Saxena if (sc->admin_reply) { 52272d1d418eSSumit Saxena if (mtx_initialized(&sc->admin_reply_lock)) 52282d1d418eSSumit Saxena mtx_destroy(&sc->admin_reply_lock); 52292d1d418eSSumit Saxena } 52302d1d418eSSumit Saxena 52312d1d418eSSumit Saxena if (sc->op_reply_q) { 52322d1d418eSSumit Saxena for(i = 0; i < sc->num_queues; i++) { 52332d1d418eSSumit Saxena op_reply_q = sc->op_reply_q + i; 52342d1d418eSSumit Saxena if (mtx_initialized(&op_reply_q->q_lock)) 52352d1d418eSSumit Saxena mtx_destroy(&op_reply_q->q_lock); 52362d1d418eSSumit Saxena } 52372d1d418eSSumit Saxena } 52382d1d418eSSumit Saxena 52392d1d418eSSumit Saxena if (sc->op_req_q) { 52402d1d418eSSumit Saxena for(i = 0; i < sc->num_queues; i++) { 52412d1d418eSSumit Saxena op_req_q = sc->op_req_q + i; 52422d1d418eSSumit Saxena if (mtx_initialized(&op_req_q->q_lock)) 52432d1d418eSSumit Saxena mtx_destroy(&op_req_q->q_lock); 52442d1d418eSSumit Saxena } 52452d1d418eSSumit Saxena } 52462d1d418eSSumit Saxena 52472d1d418eSSumit Saxena if (mtx_initialized(&sc->init_cmds.completion.lock)) 52482d1d418eSSumit Saxena mtx_destroy(&sc->init_cmds.completion.lock); 52492d1d418eSSumit Saxena 52502d1d418eSSumit Saxena if (mtx_initialized(&sc->ioctl_cmds.completion.lock)) 52512d1d418eSSumit Saxena mtx_destroy(&sc->ioctl_cmds.completion.lock); 52522d1d418eSSumit Saxena 52532d1d418eSSumit Saxena if (mtx_initialized(&sc->host_tm_cmds.completion.lock)) 52542d1d418eSSumit Saxena mtx_destroy(&sc->host_tm_cmds.completion.lock); 52552d1d418eSSumit Saxena 52562d1d418eSSumit Saxena for (i = 0; i < MPI3MR_NUM_DEVRMCMD; i++) { 52572d1d418eSSumit Saxena if (mtx_initialized(&sc->dev_rmhs_cmds[i].completion.lock)) 52582d1d418eSSumit Saxena mtx_destroy(&sc->dev_rmhs_cmds[i].completion.lock); 52592d1d418eSSumit Saxena } 52602d1d418eSSumit Saxena 52612d1d418eSSumit Saxena if (mtx_initialized(&sc->reset_mutex)) 52622d1d418eSSumit Saxena mtx_destroy(&sc->reset_mutex); 52632d1d418eSSumit Saxena 52642d1d418eSSumit Saxena if (mtx_initialized(&sc->target_lock)) 52652d1d418eSSumit Saxena mtx_destroy(&sc->target_lock); 52662d1d418eSSumit Saxena 52672d1d418eSSumit Saxena if (mtx_initialized(&sc->fwevt_lock)) 52682d1d418eSSumit Saxena mtx_destroy(&sc->fwevt_lock); 52692d1d418eSSumit Saxena 52702d1d418eSSumit Saxena if (mtx_initialized(&sc->cmd_pool_lock)) 52712d1d418eSSumit Saxena mtx_destroy(&sc->cmd_pool_lock); 52722d1d418eSSumit Saxena 52732d1d418eSSumit Saxena if (mtx_initialized(&sc->reply_free_q_lock)) 52742d1d418eSSumit Saxena mtx_destroy(&sc->reply_free_q_lock); 52752d1d418eSSumit Saxena 52762d1d418eSSumit Saxena if (mtx_initialized(&sc->sense_buf_q_lock)) 52772d1d418eSSumit Saxena mtx_destroy(&sc->sense_buf_q_lock); 52782d1d418eSSumit Saxena 52792d1d418eSSumit Saxena if (mtx_initialized(&sc->chain_buf_lock)) 52802d1d418eSSumit Saxena mtx_destroy(&sc->chain_buf_lock); 52812d1d418eSSumit Saxena 52822d1d418eSSumit Saxena if (mtx_initialized(&sc->admin_req_lock)) 52832d1d418eSSumit Saxena mtx_destroy(&sc->admin_req_lock); 52842d1d418eSSumit Saxena 52852d1d418eSSumit Saxena if (mtx_initialized(&sc->mpi3mr_mtx)) 52862d1d418eSSumit Saxena mtx_destroy(&sc->mpi3mr_mtx); 52872d1d418eSSumit Saxena } 52882d1d418eSSumit Saxena 52892d1d418eSSumit Saxena /** 52902d1d418eSSumit Saxena * mpi3mr_free_mem - Freeup adapter level data structures 52912d1d418eSSumit Saxena * @sc: Adapter reference 52922d1d418eSSumit Saxena * 52932d1d418eSSumit Saxena * Return: Nothing. 52942d1d418eSSumit Saxena */ 52952d1d418eSSumit Saxena void 52962d1d418eSSumit Saxena mpi3mr_free_mem(struct mpi3mr_softc *sc) 52972d1d418eSSumit Saxena { 52982d1d418eSSumit Saxena int i; 52992d1d418eSSumit Saxena struct mpi3mr_op_req_queue *op_req_q; 53002d1d418eSSumit Saxena struct mpi3mr_op_reply_queue *op_reply_q; 53012d1d418eSSumit Saxena struct mpi3mr_irq_context *irq_ctx; 53022d1d418eSSumit Saxena 53032d1d418eSSumit Saxena if (sc->cmd_list) { 53042d1d418eSSumit Saxena for (i = 0; i < sc->max_host_ios; i++) { 53052d1d418eSSumit Saxena free(sc->cmd_list[i], M_MPI3MR); 53062d1d418eSSumit Saxena } 53072d1d418eSSumit Saxena free(sc->cmd_list, M_MPI3MR); 53082d1d418eSSumit Saxena sc->cmd_list = NULL; 53092d1d418eSSumit Saxena } 53102d1d418eSSumit Saxena 53112d1d418eSSumit Saxena if (sc->pel_seq_number && sc->pel_seq_number_dma) { 53122d1d418eSSumit Saxena bus_dmamap_unload(sc->pel_seq_num_dmatag, sc->pel_seq_num_dmamap); 53132d1d418eSSumit Saxena bus_dmamem_free(sc->pel_seq_num_dmatag, sc->pel_seq_number, sc->pel_seq_num_dmamap); 53142d1d418eSSumit Saxena sc->pel_seq_number = NULL; 53152d1d418eSSumit Saxena if (sc->pel_seq_num_dmatag != NULL) 53162d1d418eSSumit Saxena bus_dma_tag_destroy(sc->pel_seq_num_dmatag); 53172d1d418eSSumit Saxena } 53182d1d418eSSumit Saxena 53192d1d418eSSumit Saxena if (sc->throttle_groups) { 53202d1d418eSSumit Saxena free(sc->throttle_groups, M_MPI3MR); 53212d1d418eSSumit Saxena sc->throttle_groups = NULL; 53222d1d418eSSumit Saxena } 53232d1d418eSSumit Saxena 53242d1d418eSSumit Saxena /* Free up operational queues*/ 53252d1d418eSSumit Saxena if (sc->op_req_q) { 53262d1d418eSSumit Saxena for (i = 0; i < sc->num_queues; i++) { 53272d1d418eSSumit Saxena op_req_q = sc->op_req_q + i; 53282d1d418eSSumit Saxena if (op_req_q->q_base && op_req_q->q_base_phys) { 53292d1d418eSSumit Saxena bus_dmamap_unload(op_req_q->q_base_tag, op_req_q->q_base_dmamap); 53302d1d418eSSumit Saxena bus_dmamem_free(op_req_q->q_base_tag, op_req_q->q_base, op_req_q->q_base_dmamap); 53312d1d418eSSumit Saxena op_req_q->q_base = NULL; 53322d1d418eSSumit Saxena if (op_req_q->q_base_tag != NULL) 53332d1d418eSSumit Saxena bus_dma_tag_destroy(op_req_q->q_base_tag); 53342d1d418eSSumit Saxena } 53352d1d418eSSumit Saxena } 53362d1d418eSSumit Saxena free(sc->op_req_q, M_MPI3MR); 53372d1d418eSSumit Saxena sc->op_req_q = NULL; 53382d1d418eSSumit Saxena } 53392d1d418eSSumit Saxena 53402d1d418eSSumit Saxena if (sc->op_reply_q) { 53412d1d418eSSumit Saxena for (i = 0; i < sc->num_queues; i++) { 53422d1d418eSSumit Saxena op_reply_q = sc->op_reply_q + i; 53432d1d418eSSumit Saxena if (op_reply_q->q_base && op_reply_q->q_base_phys) { 53442d1d418eSSumit Saxena bus_dmamap_unload(op_reply_q->q_base_tag, op_reply_q->q_base_dmamap); 53452d1d418eSSumit Saxena bus_dmamem_free(op_reply_q->q_base_tag, op_reply_q->q_base, op_reply_q->q_base_dmamap); 53462d1d418eSSumit Saxena op_reply_q->q_base = NULL; 53472d1d418eSSumit Saxena if (op_reply_q->q_base_tag != NULL) 53482d1d418eSSumit Saxena bus_dma_tag_destroy(op_reply_q->q_base_tag); 53492d1d418eSSumit Saxena } 53502d1d418eSSumit Saxena } 53512d1d418eSSumit Saxena free(sc->op_reply_q, M_MPI3MR); 53522d1d418eSSumit Saxena sc->op_reply_q = NULL; 53532d1d418eSSumit Saxena } 53542d1d418eSSumit Saxena 53552d1d418eSSumit Saxena /* Free up chain buffers*/ 53562d1d418eSSumit Saxena if (sc->chain_sgl_list) { 53572d1d418eSSumit Saxena for (i = 0; i < sc->chain_buf_count; i++) { 53582d1d418eSSumit Saxena if (sc->chain_sgl_list[i].buf && sc->chain_sgl_list[i].buf_phys) { 53592d1d418eSSumit Saxena bus_dmamap_unload(sc->chain_sgl_list_tag, sc->chain_sgl_list[i].buf_dmamap); 53602d1d418eSSumit Saxena bus_dmamem_free(sc->chain_sgl_list_tag, sc->chain_sgl_list[i].buf, 53612d1d418eSSumit Saxena sc->chain_sgl_list[i].buf_dmamap); 53622d1d418eSSumit Saxena sc->chain_sgl_list[i].buf = NULL; 53632d1d418eSSumit Saxena } 53642d1d418eSSumit Saxena } 53652d1d418eSSumit Saxena if (sc->chain_sgl_list_tag != NULL) 53662d1d418eSSumit Saxena bus_dma_tag_destroy(sc->chain_sgl_list_tag); 53672d1d418eSSumit Saxena free(sc->chain_sgl_list, M_MPI3MR); 53682d1d418eSSumit Saxena sc->chain_sgl_list = NULL; 53692d1d418eSSumit Saxena } 53702d1d418eSSumit Saxena 53712d1d418eSSumit Saxena if (sc->chain_bitmap) { 53722d1d418eSSumit Saxena free(sc->chain_bitmap, M_MPI3MR); 53732d1d418eSSumit Saxena sc->chain_bitmap = NULL; 53742d1d418eSSumit Saxena } 53752d1d418eSSumit Saxena 53762d1d418eSSumit Saxena for (i = 0; i < sc->msix_count; i++) { 53772d1d418eSSumit Saxena irq_ctx = sc->irq_ctx + i; 53782d1d418eSSumit Saxena if (irq_ctx) 53792d1d418eSSumit Saxena irq_ctx->op_reply_q = NULL; 53802d1d418eSSumit Saxena } 53812d1d418eSSumit Saxena 53822d1d418eSSumit Saxena /* Free reply_buf_tag */ 53832d1d418eSSumit Saxena if (sc->reply_buf && sc->reply_buf_phys) { 53842d1d418eSSumit Saxena bus_dmamap_unload(sc->reply_buf_tag, sc->reply_buf_dmamap); 53852d1d418eSSumit Saxena bus_dmamem_free(sc->reply_buf_tag, sc->reply_buf, 53862d1d418eSSumit Saxena sc->reply_buf_dmamap); 53872d1d418eSSumit Saxena sc->reply_buf = NULL; 53882d1d418eSSumit Saxena if (sc->reply_buf_tag != NULL) 53892d1d418eSSumit Saxena bus_dma_tag_destroy(sc->reply_buf_tag); 53902d1d418eSSumit Saxena } 53912d1d418eSSumit Saxena 53922d1d418eSSumit Saxena /* Free reply_free_q_tag */ 53932d1d418eSSumit Saxena if (sc->reply_free_q && sc->reply_free_q_phys) { 53942d1d418eSSumit Saxena bus_dmamap_unload(sc->reply_free_q_tag, sc->reply_free_q_dmamap); 53952d1d418eSSumit Saxena bus_dmamem_free(sc->reply_free_q_tag, sc->reply_free_q, 53962d1d418eSSumit Saxena sc->reply_free_q_dmamap); 53972d1d418eSSumit Saxena sc->reply_free_q = NULL; 53982d1d418eSSumit Saxena if (sc->reply_free_q_tag != NULL) 53992d1d418eSSumit Saxena bus_dma_tag_destroy(sc->reply_free_q_tag); 54002d1d418eSSumit Saxena } 54012d1d418eSSumit Saxena 54022d1d418eSSumit Saxena /* Free sense_buf_tag */ 54032d1d418eSSumit Saxena if (sc->sense_buf && sc->sense_buf_phys) { 54042d1d418eSSumit Saxena bus_dmamap_unload(sc->sense_buf_tag, sc->sense_buf_dmamap); 54052d1d418eSSumit Saxena bus_dmamem_free(sc->sense_buf_tag, sc->sense_buf, 54062d1d418eSSumit Saxena sc->sense_buf_dmamap); 54072d1d418eSSumit Saxena sc->sense_buf = NULL; 54082d1d418eSSumit Saxena if (sc->sense_buf_tag != NULL) 54092d1d418eSSumit Saxena bus_dma_tag_destroy(sc->sense_buf_tag); 54102d1d418eSSumit Saxena } 54112d1d418eSSumit Saxena 54122d1d418eSSumit Saxena /* Free sense_buf_q_tag */ 54132d1d418eSSumit Saxena if (sc->sense_buf_q && sc->sense_buf_q_phys) { 54142d1d418eSSumit Saxena bus_dmamap_unload(sc->sense_buf_q_tag, sc->sense_buf_q_dmamap); 54152d1d418eSSumit Saxena bus_dmamem_free(sc->sense_buf_q_tag, sc->sense_buf_q, 54162d1d418eSSumit Saxena sc->sense_buf_q_dmamap); 54172d1d418eSSumit Saxena sc->sense_buf_q = NULL; 54182d1d418eSSumit Saxena if (sc->sense_buf_q_tag != NULL) 54192d1d418eSSumit Saxena bus_dma_tag_destroy(sc->sense_buf_q_tag); 54202d1d418eSSumit Saxena } 54212d1d418eSSumit Saxena 54222d1d418eSSumit Saxena /* Free up internal(non-IO) commands*/ 54232d1d418eSSumit Saxena if (sc->init_cmds.reply) { 54242d1d418eSSumit Saxena free(sc->init_cmds.reply, M_MPI3MR); 54252d1d418eSSumit Saxena sc->init_cmds.reply = NULL; 54262d1d418eSSumit Saxena } 54272d1d418eSSumit Saxena 54282d1d418eSSumit Saxena if (sc->ioctl_cmds.reply) { 54292d1d418eSSumit Saxena free(sc->ioctl_cmds.reply, M_MPI3MR); 54302d1d418eSSumit Saxena sc->ioctl_cmds.reply = NULL; 54312d1d418eSSumit Saxena } 54322d1d418eSSumit Saxena 54332d1d418eSSumit Saxena if (sc->pel_cmds.reply) { 54342d1d418eSSumit Saxena free(sc->pel_cmds.reply, M_MPI3MR); 54352d1d418eSSumit Saxena sc->pel_cmds.reply = NULL; 54362d1d418eSSumit Saxena } 54372d1d418eSSumit Saxena 54382d1d418eSSumit Saxena if (sc->pel_abort_cmd.reply) { 54392d1d418eSSumit Saxena free(sc->pel_abort_cmd.reply, M_MPI3MR); 54402d1d418eSSumit Saxena sc->pel_abort_cmd.reply = NULL; 54412d1d418eSSumit Saxena } 54422d1d418eSSumit Saxena 54432d1d418eSSumit Saxena if (sc->host_tm_cmds.reply) { 54442d1d418eSSumit Saxena free(sc->host_tm_cmds.reply, M_MPI3MR); 54452d1d418eSSumit Saxena sc->host_tm_cmds.reply = NULL; 54462d1d418eSSumit Saxena } 54472d1d418eSSumit Saxena 54482d1d418eSSumit Saxena if (sc->log_data_buffer) { 54492d1d418eSSumit Saxena free(sc->log_data_buffer, M_MPI3MR); 54502d1d418eSSumit Saxena sc->log_data_buffer = NULL; 54512d1d418eSSumit Saxena } 54522d1d418eSSumit Saxena 54532d1d418eSSumit Saxena for (i = 0; i < MPI3MR_NUM_DEVRMCMD; i++) { 54542d1d418eSSumit Saxena if (sc->dev_rmhs_cmds[i].reply) { 54552d1d418eSSumit Saxena free(sc->dev_rmhs_cmds[i].reply, M_MPI3MR); 54562d1d418eSSumit Saxena sc->dev_rmhs_cmds[i].reply = NULL; 54572d1d418eSSumit Saxena } 54582d1d418eSSumit Saxena } 54592d1d418eSSumit Saxena 54602d1d418eSSumit Saxena for (i = 0; i < MPI3MR_NUM_EVTACKCMD; i++) { 54612d1d418eSSumit Saxena if (sc->evtack_cmds[i].reply) { 54622d1d418eSSumit Saxena free(sc->evtack_cmds[i].reply, M_MPI3MR); 54632d1d418eSSumit Saxena sc->evtack_cmds[i].reply = NULL; 54642d1d418eSSumit Saxena } 54652d1d418eSSumit Saxena } 54662d1d418eSSumit Saxena 54672d1d418eSSumit Saxena if (sc->removepend_bitmap) { 54682d1d418eSSumit Saxena free(sc->removepend_bitmap, M_MPI3MR); 54692d1d418eSSumit Saxena sc->removepend_bitmap = NULL; 54702d1d418eSSumit Saxena } 54712d1d418eSSumit Saxena 54722d1d418eSSumit Saxena if (sc->devrem_bitmap) { 54732d1d418eSSumit Saxena free(sc->devrem_bitmap, M_MPI3MR); 54742d1d418eSSumit Saxena sc->devrem_bitmap = NULL; 54752d1d418eSSumit Saxena } 54762d1d418eSSumit Saxena 54772d1d418eSSumit Saxena if (sc->evtack_cmds_bitmap) { 54782d1d418eSSumit Saxena free(sc->evtack_cmds_bitmap, M_MPI3MR); 54792d1d418eSSumit Saxena sc->evtack_cmds_bitmap = NULL; 54802d1d418eSSumit Saxena } 54812d1d418eSSumit Saxena 54822d1d418eSSumit Saxena /* Free Admin reply*/ 54832d1d418eSSumit Saxena if (sc->admin_reply && sc->admin_reply_phys) { 54842d1d418eSSumit Saxena bus_dmamap_unload(sc->admin_reply_tag, sc->admin_reply_dmamap); 54852d1d418eSSumit Saxena bus_dmamem_free(sc->admin_reply_tag, sc->admin_reply, 54862d1d418eSSumit Saxena sc->admin_reply_dmamap); 54872d1d418eSSumit Saxena sc->admin_reply = NULL; 54882d1d418eSSumit Saxena if (sc->admin_reply_tag != NULL) 54892d1d418eSSumit Saxena bus_dma_tag_destroy(sc->admin_reply_tag); 54902d1d418eSSumit Saxena } 54912d1d418eSSumit Saxena 54922d1d418eSSumit Saxena /* Free Admin request*/ 54932d1d418eSSumit Saxena if (sc->admin_req && sc->admin_req_phys) { 54942d1d418eSSumit Saxena bus_dmamap_unload(sc->admin_req_tag, sc->admin_req_dmamap); 54952d1d418eSSumit Saxena bus_dmamem_free(sc->admin_req_tag, sc->admin_req, 54962d1d418eSSumit Saxena sc->admin_req_dmamap); 54972d1d418eSSumit Saxena sc->admin_req = NULL; 54982d1d418eSSumit Saxena if (sc->admin_req_tag != NULL) 54992d1d418eSSumit Saxena bus_dma_tag_destroy(sc->admin_req_tag); 55002d1d418eSSumit Saxena } 55012d1d418eSSumit Saxena mpi3mr_free_ioctl_dma_memory(sc); 55022d1d418eSSumit Saxena 55032d1d418eSSumit Saxena } 55042d1d418eSSumit Saxena 55052d1d418eSSumit Saxena /** 55062d1d418eSSumit Saxena * mpi3mr_drv_cmd_comp_reset - Flush a internal driver command 55072d1d418eSSumit Saxena * @sc: Adapter instance reference 55082d1d418eSSumit Saxena * @cmdptr: Internal command tracker 55092d1d418eSSumit Saxena * 55102d1d418eSSumit Saxena * Complete an internal driver commands with state indicating it 55112d1d418eSSumit Saxena * is completed due to reset. 55122d1d418eSSumit Saxena * 55132d1d418eSSumit Saxena * Return: Nothing. 55142d1d418eSSumit Saxena */ 55152d1d418eSSumit Saxena static inline void mpi3mr_drv_cmd_comp_reset(struct mpi3mr_softc *sc, 55162d1d418eSSumit Saxena struct mpi3mr_drvr_cmd *cmdptr) 55172d1d418eSSumit Saxena { 55182d1d418eSSumit Saxena if (cmdptr->state & MPI3MR_CMD_PENDING) { 55192d1d418eSSumit Saxena cmdptr->state |= MPI3MR_CMD_RESET; 55202d1d418eSSumit Saxena cmdptr->state &= ~MPI3MR_CMD_PENDING; 55212d1d418eSSumit Saxena if (cmdptr->is_waiting) { 55222d1d418eSSumit Saxena complete(&cmdptr->completion); 55232d1d418eSSumit Saxena cmdptr->is_waiting = 0; 55242d1d418eSSumit Saxena } else if (cmdptr->callback) 55252d1d418eSSumit Saxena cmdptr->callback(sc, cmdptr); 55262d1d418eSSumit Saxena } 55272d1d418eSSumit Saxena } 55282d1d418eSSumit Saxena 55292d1d418eSSumit Saxena /** 55302d1d418eSSumit Saxena * mpi3mr_flush_drv_cmds - Flush internal driver commands 55312d1d418eSSumit Saxena * @sc: Adapter instance reference 55322d1d418eSSumit Saxena * 55332d1d418eSSumit Saxena * Flush all internal driver commands post reset 55342d1d418eSSumit Saxena * 55352d1d418eSSumit Saxena * Return: Nothing. 55362d1d418eSSumit Saxena */ 55372d1d418eSSumit Saxena static void mpi3mr_flush_drv_cmds(struct mpi3mr_softc *sc) 55382d1d418eSSumit Saxena { 55392d1d418eSSumit Saxena int i = 0; 55402d1d418eSSumit Saxena struct mpi3mr_drvr_cmd *cmdptr; 55412d1d418eSSumit Saxena 55422d1d418eSSumit Saxena cmdptr = &sc->init_cmds; 55432d1d418eSSumit Saxena mpi3mr_drv_cmd_comp_reset(sc, cmdptr); 55442d1d418eSSumit Saxena 55452d1d418eSSumit Saxena cmdptr = &sc->ioctl_cmds; 55462d1d418eSSumit Saxena mpi3mr_drv_cmd_comp_reset(sc, cmdptr); 55472d1d418eSSumit Saxena 55482d1d418eSSumit Saxena cmdptr = &sc->host_tm_cmds; 55492d1d418eSSumit Saxena mpi3mr_drv_cmd_comp_reset(sc, cmdptr); 55502d1d418eSSumit Saxena 55512d1d418eSSumit Saxena for (i = 0; i < MPI3MR_NUM_DEVRMCMD; i++) { 55522d1d418eSSumit Saxena cmdptr = &sc->dev_rmhs_cmds[i]; 55532d1d418eSSumit Saxena mpi3mr_drv_cmd_comp_reset(sc, cmdptr); 55542d1d418eSSumit Saxena } 55552d1d418eSSumit Saxena 55562d1d418eSSumit Saxena for (i = 0; i < MPI3MR_NUM_EVTACKCMD; i++) { 55572d1d418eSSumit Saxena cmdptr = &sc->evtack_cmds[i]; 55582d1d418eSSumit Saxena mpi3mr_drv_cmd_comp_reset(sc, cmdptr); 55592d1d418eSSumit Saxena } 55602d1d418eSSumit Saxena 55612d1d418eSSumit Saxena cmdptr = &sc->pel_cmds; 55622d1d418eSSumit Saxena mpi3mr_drv_cmd_comp_reset(sc, cmdptr); 55632d1d418eSSumit Saxena 55642d1d418eSSumit Saxena cmdptr = &sc->pel_abort_cmd; 55652d1d418eSSumit Saxena mpi3mr_drv_cmd_comp_reset(sc, cmdptr); 55662d1d418eSSumit Saxena } 55672d1d418eSSumit Saxena 55682d1d418eSSumit Saxena 55692d1d418eSSumit Saxena /** 55702d1d418eSSumit Saxena * mpi3mr_memset_buffers - memset memory for a controller 55712d1d418eSSumit Saxena * @sc: Adapter instance reference 55722d1d418eSSumit Saxena * 55732d1d418eSSumit Saxena * clear all the memory allocated for a controller, typically 55742d1d418eSSumit Saxena * called post reset to reuse the memory allocated during the 55752d1d418eSSumit Saxena * controller init. 55762d1d418eSSumit Saxena * 55772d1d418eSSumit Saxena * Return: Nothing. 55782d1d418eSSumit Saxena */ 55792d1d418eSSumit Saxena static void mpi3mr_memset_buffers(struct mpi3mr_softc *sc) 55802d1d418eSSumit Saxena { 55812d1d418eSSumit Saxena U16 i; 55822d1d418eSSumit Saxena struct mpi3mr_throttle_group_info *tg; 55832d1d418eSSumit Saxena 55842d1d418eSSumit Saxena memset(sc->admin_req, 0, sc->admin_req_q_sz); 55852d1d418eSSumit Saxena memset(sc->admin_reply, 0, sc->admin_reply_q_sz); 55862d1d418eSSumit Saxena 55872d1d418eSSumit Saxena memset(sc->init_cmds.reply, 0, sc->reply_sz); 55882d1d418eSSumit Saxena memset(sc->ioctl_cmds.reply, 0, sc->reply_sz); 55892d1d418eSSumit Saxena memset(sc->host_tm_cmds.reply, 0, sc->reply_sz); 55902d1d418eSSumit Saxena memset(sc->pel_cmds.reply, 0, sc->reply_sz); 55912d1d418eSSumit Saxena memset(sc->pel_abort_cmd.reply, 0, sc->reply_sz); 55922d1d418eSSumit Saxena for (i = 0; i < MPI3MR_NUM_DEVRMCMD; i++) 55932d1d418eSSumit Saxena memset(sc->dev_rmhs_cmds[i].reply, 0, sc->reply_sz); 55942d1d418eSSumit Saxena for (i = 0; i < MPI3MR_NUM_EVTACKCMD; i++) 55952d1d418eSSumit Saxena memset(sc->evtack_cmds[i].reply, 0, sc->reply_sz); 55962d1d418eSSumit Saxena memset(sc->removepend_bitmap, 0, sc->dev_handle_bitmap_sz); 55972d1d418eSSumit Saxena memset(sc->devrem_bitmap, 0, sc->devrem_bitmap_sz); 55982d1d418eSSumit Saxena memset(sc->evtack_cmds_bitmap, 0, sc->evtack_cmds_bitmap_sz); 55992d1d418eSSumit Saxena 56002d1d418eSSumit Saxena for (i = 0; i < sc->num_queues; i++) { 56012d1d418eSSumit Saxena sc->op_reply_q[i].qid = 0; 56022d1d418eSSumit Saxena sc->op_reply_q[i].ci = 0; 56032d1d418eSSumit Saxena sc->op_reply_q[i].num_replies = 0; 56042d1d418eSSumit Saxena sc->op_reply_q[i].ephase = 0; 56052d1d418eSSumit Saxena mpi3mr_atomic_set(&sc->op_reply_q[i].pend_ios, 0); 56062d1d418eSSumit Saxena memset(sc->op_reply_q[i].q_base, 0, sc->op_reply_q[i].qsz); 56072d1d418eSSumit Saxena 56082d1d418eSSumit Saxena sc->op_req_q[i].ci = 0; 56092d1d418eSSumit Saxena sc->op_req_q[i].pi = 0; 56102d1d418eSSumit Saxena sc->op_req_q[i].num_reqs = 0; 56112d1d418eSSumit Saxena sc->op_req_q[i].qid = 0; 56122d1d418eSSumit Saxena sc->op_req_q[i].reply_qid = 0; 56132d1d418eSSumit Saxena memset(sc->op_req_q[i].q_base, 0, sc->op_req_q[i].qsz); 56142d1d418eSSumit Saxena } 56152d1d418eSSumit Saxena 56162d1d418eSSumit Saxena mpi3mr_atomic_set(&sc->pend_large_data_sz, 0); 56172d1d418eSSumit Saxena if (sc->throttle_groups) { 56182d1d418eSSumit Saxena tg = sc->throttle_groups; 56192d1d418eSSumit Saxena for (i = 0; i < sc->num_io_throttle_group; i++, tg++) { 56202d1d418eSSumit Saxena tg->id = 0; 56212d1d418eSSumit Saxena tg->fw_qd = 0; 56222d1d418eSSumit Saxena tg->modified_qd = 0; 56232d1d418eSSumit Saxena tg->io_divert= 0; 56242d1d418eSSumit Saxena tg->high = 0; 56252d1d418eSSumit Saxena tg->low = 0; 56262d1d418eSSumit Saxena mpi3mr_atomic_set(&tg->pend_large_data_sz, 0); 56272d1d418eSSumit Saxena } 56282d1d418eSSumit Saxena } 56292d1d418eSSumit Saxena } 56302d1d418eSSumit Saxena 56312d1d418eSSumit Saxena /** 56322d1d418eSSumit Saxena * mpi3mr_invalidate_devhandles -Invalidate device handles 56332d1d418eSSumit Saxena * @sc: Adapter instance reference 56342d1d418eSSumit Saxena * 56352d1d418eSSumit Saxena * Invalidate the device handles in the target device structures 56362d1d418eSSumit Saxena * . Called post reset prior to reinitializing the controller. 56372d1d418eSSumit Saxena * 56382d1d418eSSumit Saxena * Return: Nothing. 56392d1d418eSSumit Saxena */ 56402d1d418eSSumit Saxena static void mpi3mr_invalidate_devhandles(struct mpi3mr_softc *sc) 56412d1d418eSSumit Saxena { 56422d1d418eSSumit Saxena struct mpi3mr_target *target = NULL; 56432d1d418eSSumit Saxena 56442d1d418eSSumit Saxena mtx_lock_spin(&sc->target_lock); 56452d1d418eSSumit Saxena TAILQ_FOREACH(target, &sc->cam_sc->tgt_list, tgt_next) { 56462d1d418eSSumit Saxena if (target) { 56472d1d418eSSumit Saxena target->dev_handle = MPI3MR_INVALID_DEV_HANDLE; 56482d1d418eSSumit Saxena target->io_throttle_enabled = 0; 56492d1d418eSSumit Saxena target->io_divert = 0; 56502d1d418eSSumit Saxena target->throttle_group = NULL; 56512d1d418eSSumit Saxena } 56522d1d418eSSumit Saxena } 56532d1d418eSSumit Saxena mtx_unlock_spin(&sc->target_lock); 56542d1d418eSSumit Saxena } 56552d1d418eSSumit Saxena 56562d1d418eSSumit Saxena /** 56572d1d418eSSumit Saxena * mpi3mr_rfresh_tgtdevs - Refresh target device exposure 56582d1d418eSSumit Saxena * @sc: Adapter instance reference 56592d1d418eSSumit Saxena * 56602d1d418eSSumit Saxena * This is executed post controller reset to identify any 56612d1d418eSSumit Saxena * missing devices during reset and remove from the upper layers 56622d1d418eSSumit Saxena * or expose any newly detected device to the upper layers. 56632d1d418eSSumit Saxena * 56642d1d418eSSumit Saxena * Return: Nothing. 56652d1d418eSSumit Saxena */ 56662d1d418eSSumit Saxena 56672d1d418eSSumit Saxena static void mpi3mr_rfresh_tgtdevs(struct mpi3mr_softc *sc) 56682d1d418eSSumit Saxena { 56692d1d418eSSumit Saxena struct mpi3mr_target *target = NULL; 56702d1d418eSSumit Saxena struct mpi3mr_target *target_temp = NULL; 56712d1d418eSSumit Saxena 56722d1d418eSSumit Saxena TAILQ_FOREACH_SAFE(target, &sc->cam_sc->tgt_list, tgt_next, target_temp) { 56732d1d418eSSumit Saxena if (target->dev_handle == MPI3MR_INVALID_DEV_HANDLE) { 56742d1d418eSSumit Saxena if (target->exposed_to_os) 56752d1d418eSSumit Saxena mpi3mr_remove_device_from_os(sc, target->dev_handle); 56762d1d418eSSumit Saxena mpi3mr_remove_device_from_list(sc, target, true); 56770d705645SChandrakanth patil } else if (target->is_hidden && target->exposed_to_os) { 56780d705645SChandrakanth patil mpi3mr_remove_device_from_os(sc, target->dev_handle); 56792d1d418eSSumit Saxena } 56802d1d418eSSumit Saxena } 56812d1d418eSSumit Saxena 56822d1d418eSSumit Saxena TAILQ_FOREACH(target, &sc->cam_sc->tgt_list, tgt_next) { 56832d1d418eSSumit Saxena if ((target->dev_handle != MPI3MR_INVALID_DEV_HANDLE) && 56842d1d418eSSumit Saxena !target->is_hidden && !target->exposed_to_os) { 56852d1d418eSSumit Saxena mpi3mr_add_device(sc, target->per_id); 56862d1d418eSSumit Saxena } 56872d1d418eSSumit Saxena } 56882d1d418eSSumit Saxena 56892d1d418eSSumit Saxena } 56902d1d418eSSumit Saxena 56912d1d418eSSumit Saxena static void mpi3mr_flush_io(struct mpi3mr_softc *sc) 56922d1d418eSSumit Saxena { 56932d1d418eSSumit Saxena int i; 56942d1d418eSSumit Saxena struct mpi3mr_cmd *cmd = NULL; 56952d1d418eSSumit Saxena union ccb *ccb = NULL; 56962d1d418eSSumit Saxena 56972d1d418eSSumit Saxena for (i = 0; i < sc->max_host_ios; i++) { 56982d1d418eSSumit Saxena cmd = sc->cmd_list[i]; 56992d1d418eSSumit Saxena 57002d1d418eSSumit Saxena if (cmd && cmd->ccb) { 57012d1d418eSSumit Saxena if (cmd->callout_owner) { 57022d1d418eSSumit Saxena ccb = (union ccb *)(cmd->ccb); 57032d1d418eSSumit Saxena ccb->ccb_h.status = CAM_SCSI_BUS_RESET; 5704571f1d06SChandrakanth patil mpi3mr_atomic_dec(&sc->fw_outstanding); 5705571f1d06SChandrakanth patil mpi3mr_atomic_dec(&cmd->targ->outstanding); 57062d1d418eSSumit Saxena mpi3mr_cmd_done(sc, cmd); 57072d1d418eSSumit Saxena } else { 57082d1d418eSSumit Saxena cmd->ccb = NULL; 57092d1d418eSSumit Saxena mpi3mr_release_command(cmd); 57102d1d418eSSumit Saxena } 57112d1d418eSSumit Saxena } 57122d1d418eSSumit Saxena } 57132d1d418eSSumit Saxena } 57142d1d418eSSumit Saxena /** 57152d1d418eSSumit Saxena * mpi3mr_clear_reset_history - Clear reset history 57162d1d418eSSumit Saxena * @sc: Adapter instance reference 57172d1d418eSSumit Saxena * 57182d1d418eSSumit Saxena * Write the reset history bit in IOC Status to clear the bit, 57192d1d418eSSumit Saxena * if it is already set. 57202d1d418eSSumit Saxena * 57212d1d418eSSumit Saxena * Return: Nothing. 57222d1d418eSSumit Saxena */ 57232d1d418eSSumit Saxena static inline void mpi3mr_clear_reset_history(struct mpi3mr_softc *sc) 57242d1d418eSSumit Saxena { 57252d1d418eSSumit Saxena U32 ioc_status; 57262d1d418eSSumit Saxena 57272d1d418eSSumit Saxena ioc_status = mpi3mr_regread(sc, MPI3_SYSIF_IOC_STATUS_OFFSET); 57282d1d418eSSumit Saxena if (ioc_status & MPI3_SYSIF_IOC_STATUS_RESET_HISTORY) 57292d1d418eSSumit Saxena mpi3mr_regwrite(sc, MPI3_SYSIF_IOC_STATUS_OFFSET, ioc_status); 57302d1d418eSSumit Saxena } 57312d1d418eSSumit Saxena 57322d1d418eSSumit Saxena /** 57332d1d418eSSumit Saxena * mpi3mr_set_diagsave - Set diag save bit for snapdump 57342d1d418eSSumit Saxena * @sc: Adapter reference 57352d1d418eSSumit Saxena * 57362d1d418eSSumit Saxena * Set diag save bit in IOC configuration register to enable 57372d1d418eSSumit Saxena * snapdump. 57382d1d418eSSumit Saxena * 57392d1d418eSSumit Saxena * Return: Nothing. 57402d1d418eSSumit Saxena */ 57412d1d418eSSumit Saxena static inline void mpi3mr_set_diagsave(struct mpi3mr_softc *sc) 57422d1d418eSSumit Saxena { 57432d1d418eSSumit Saxena U32 ioc_config; 57442d1d418eSSumit Saxena 57452d1d418eSSumit Saxena ioc_config = 57462d1d418eSSumit Saxena mpi3mr_regread(sc, MPI3_SYSIF_IOC_CONFIG_OFFSET); 57472d1d418eSSumit Saxena ioc_config |= MPI3_SYSIF_IOC_CONFIG_DIAG_SAVE; 57482d1d418eSSumit Saxena mpi3mr_regwrite(sc, MPI3_SYSIF_IOC_CONFIG_OFFSET, ioc_config); 57492d1d418eSSumit Saxena } 57502d1d418eSSumit Saxena 57512d1d418eSSumit Saxena /** 57522d1d418eSSumit Saxena * mpi3mr_issue_reset - Issue reset to the controller 57532d1d418eSSumit Saxena * @sc: Adapter reference 57542d1d418eSSumit Saxena * @reset_type: Reset type 57552d1d418eSSumit Saxena * @reset_reason: Reset reason code 57562d1d418eSSumit Saxena * 57572d1d418eSSumit Saxena * Unlock the host diagnostic registers and write the specific 57582d1d418eSSumit Saxena * reset type to that, wait for reset acknowledgement from the 57592d1d418eSSumit Saxena * controller, if the reset is not successful retry for the 57602d1d418eSSumit Saxena * predefined number of times. 57612d1d418eSSumit Saxena * 57622d1d418eSSumit Saxena * Return: 0 on success, non-zero on failure. 57632d1d418eSSumit Saxena */ 57642d1d418eSSumit Saxena static int mpi3mr_issue_reset(struct mpi3mr_softc *sc, U16 reset_type, 57653012fa8fSChandrakanth patil U16 reset_reason) 57662d1d418eSSumit Saxena { 57672d1d418eSSumit Saxena int retval = -1; 57682d1d418eSSumit Saxena U8 unlock_retry_count = 0; 57693012fa8fSChandrakanth patil U32 host_diagnostic, ioc_status, ioc_config, scratch_pad0; 57702d1d418eSSumit Saxena U32 timeout = MPI3MR_RESET_ACK_TIMEOUT * 10; 57712d1d418eSSumit Saxena 57722d1d418eSSumit Saxena if ((reset_type != MPI3_SYSIF_HOST_DIAG_RESET_ACTION_SOFT_RESET) && 57732d1d418eSSumit Saxena (reset_type != MPI3_SYSIF_HOST_DIAG_RESET_ACTION_DIAG_FAULT)) 57742d1d418eSSumit Saxena return retval; 57752d1d418eSSumit Saxena if (sc->unrecoverable) 57762d1d418eSSumit Saxena return retval; 57772d1d418eSSumit Saxena 57782d1d418eSSumit Saxena if (reset_reason == MPI3MR_RESET_FROM_FIRMWARE) { 57792d1d418eSSumit Saxena retval = 0; 57802d1d418eSSumit Saxena return retval; 57812d1d418eSSumit Saxena } 57822d1d418eSSumit Saxena 57832d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_INFO, "%s reset due to %s(0x%x)\n", 57842d1d418eSSumit Saxena mpi3mr_reset_type_name(reset_type), 57852d1d418eSSumit Saxena mpi3mr_reset_rc_name(reset_reason), reset_reason); 57862d1d418eSSumit Saxena 57872d1d418eSSumit Saxena mpi3mr_clear_reset_history(sc); 57882d1d418eSSumit Saxena do { 57892d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_INFO, 57902d1d418eSSumit Saxena "Write magic sequence to unlock host diag register (retry=%d)\n", 57912d1d418eSSumit Saxena ++unlock_retry_count); 57922d1d418eSSumit Saxena if (unlock_retry_count >= MPI3MR_HOSTDIAG_UNLOCK_RETRY_COUNT) { 57932d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_ERROR, 57942d1d418eSSumit Saxena "%s reset failed! due to host diag register unlock failure" 57952d1d418eSSumit Saxena "host_diagnostic(0x%08x)\n", mpi3mr_reset_type_name(reset_type), 57962d1d418eSSumit Saxena host_diagnostic); 57972d1d418eSSumit Saxena sc->unrecoverable = 1; 57982d1d418eSSumit Saxena return retval; 57992d1d418eSSumit Saxena } 58002d1d418eSSumit Saxena 58012d1d418eSSumit Saxena mpi3mr_regwrite(sc, MPI3_SYSIF_WRITE_SEQUENCE_OFFSET, 58022d1d418eSSumit Saxena MPI3_SYSIF_WRITE_SEQUENCE_KEY_VALUE_FLUSH); 58032d1d418eSSumit Saxena mpi3mr_regwrite(sc, MPI3_SYSIF_WRITE_SEQUENCE_OFFSET, 58042d1d418eSSumit Saxena MPI3_SYSIF_WRITE_SEQUENCE_KEY_VALUE_1ST); 58052d1d418eSSumit Saxena mpi3mr_regwrite(sc, MPI3_SYSIF_WRITE_SEQUENCE_OFFSET, 58062d1d418eSSumit Saxena MPI3_SYSIF_WRITE_SEQUENCE_KEY_VALUE_2ND); 58072d1d418eSSumit Saxena mpi3mr_regwrite(sc, MPI3_SYSIF_WRITE_SEQUENCE_OFFSET, 58082d1d418eSSumit Saxena MPI3_SYSIF_WRITE_SEQUENCE_KEY_VALUE_3RD); 58092d1d418eSSumit Saxena mpi3mr_regwrite(sc, MPI3_SYSIF_WRITE_SEQUENCE_OFFSET, 58102d1d418eSSumit Saxena MPI3_SYSIF_WRITE_SEQUENCE_KEY_VALUE_4TH); 58112d1d418eSSumit Saxena mpi3mr_regwrite(sc, MPI3_SYSIF_WRITE_SEQUENCE_OFFSET, 58122d1d418eSSumit Saxena MPI3_SYSIF_WRITE_SEQUENCE_KEY_VALUE_5TH); 58132d1d418eSSumit Saxena mpi3mr_regwrite(sc, MPI3_SYSIF_WRITE_SEQUENCE_OFFSET, 58142d1d418eSSumit Saxena MPI3_SYSIF_WRITE_SEQUENCE_KEY_VALUE_6TH); 58152d1d418eSSumit Saxena 58162d1d418eSSumit Saxena DELAY(1000); /* delay in usec */ 58172d1d418eSSumit Saxena host_diagnostic = mpi3mr_regread(sc, MPI3_SYSIF_HOST_DIAG_OFFSET); 58182d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_INFO, 58192d1d418eSSumit Saxena "wrote magic sequence: retry_count(%d), host_diagnostic(0x%08x)\n", 58202d1d418eSSumit Saxena unlock_retry_count, host_diagnostic); 58212d1d418eSSumit Saxena } while (!(host_diagnostic & MPI3_SYSIF_HOST_DIAG_DIAG_WRITE_ENABLE)); 58222d1d418eSSumit Saxena 58233012fa8fSChandrakanth patil scratch_pad0 = ((MPI3MR_RESET_REASON_OSTYPE_FREEBSD << 58243012fa8fSChandrakanth patil MPI3MR_RESET_REASON_OSTYPE_SHIFT) | 58253012fa8fSChandrakanth patil (sc->facts.ioc_num << 58263012fa8fSChandrakanth patil MPI3MR_RESET_REASON_IOCNUM_SHIFT) | reset_reason); 58273012fa8fSChandrakanth patil mpi3mr_regwrite(sc, MPI3_SYSIF_SCRATCHPAD0_OFFSET, scratch_pad0); 58282d1d418eSSumit Saxena mpi3mr_regwrite(sc, MPI3_SYSIF_HOST_DIAG_OFFSET, host_diagnostic | reset_type); 58292d1d418eSSumit Saxena 58302d1d418eSSumit Saxena if (reset_type == MPI3_SYSIF_HOST_DIAG_RESET_ACTION_SOFT_RESET) { 58312d1d418eSSumit Saxena do { 58322d1d418eSSumit Saxena ioc_status = mpi3mr_regread(sc, MPI3_SYSIF_IOC_STATUS_OFFSET); 58332d1d418eSSumit Saxena if (ioc_status & 58342d1d418eSSumit Saxena MPI3_SYSIF_IOC_STATUS_RESET_HISTORY) { 58352d1d418eSSumit Saxena ioc_config = 58362d1d418eSSumit Saxena mpi3mr_regread(sc, MPI3_SYSIF_IOC_CONFIG_OFFSET); 58372d1d418eSSumit Saxena if (mpi3mr_soft_reset_success(ioc_status, 58382d1d418eSSumit Saxena ioc_config)) { 58392d1d418eSSumit Saxena mpi3mr_clear_reset_history(sc); 58402d1d418eSSumit Saxena retval = 0; 58412d1d418eSSumit Saxena break; 58422d1d418eSSumit Saxena } 58432d1d418eSSumit Saxena } 58442d1d418eSSumit Saxena DELAY(100 * 1000); 58452d1d418eSSumit Saxena } while (--timeout); 58462d1d418eSSumit Saxena } else if (reset_type == MPI3_SYSIF_HOST_DIAG_RESET_ACTION_DIAG_FAULT) { 58472d1d418eSSumit Saxena do { 58482d1d418eSSumit Saxena ioc_status = mpi3mr_regread(sc, MPI3_SYSIF_IOC_STATUS_OFFSET); 58492d1d418eSSumit Saxena if (mpi3mr_diagfault_success(sc, ioc_status)) { 58502d1d418eSSumit Saxena retval = 0; 58512d1d418eSSumit Saxena break; 58522d1d418eSSumit Saxena } 58532d1d418eSSumit Saxena DELAY(100 * 1000); 58542d1d418eSSumit Saxena } while (--timeout); 58552d1d418eSSumit Saxena } 58562d1d418eSSumit Saxena 58572d1d418eSSumit Saxena mpi3mr_regwrite(sc, MPI3_SYSIF_WRITE_SEQUENCE_OFFSET, 58582d1d418eSSumit Saxena MPI3_SYSIF_WRITE_SEQUENCE_KEY_VALUE_2ND); 58592d1d418eSSumit Saxena 58602d1d418eSSumit Saxena ioc_status = mpi3mr_regread(sc, MPI3_SYSIF_IOC_STATUS_OFFSET); 58612d1d418eSSumit Saxena ioc_config = mpi3mr_regread(sc, MPI3_SYSIF_IOC_CONFIG_OFFSET); 58622d1d418eSSumit Saxena 58632d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_INFO, 58642d1d418eSSumit Saxena "IOC Status/Config after %s reset is (0x%x)/(0x%x)\n", 58652d1d418eSSumit Saxena !retval ? "successful":"failed", ioc_status, 58662d1d418eSSumit Saxena ioc_config); 58672d1d418eSSumit Saxena 58682d1d418eSSumit Saxena if (retval) 58692d1d418eSSumit Saxena sc->unrecoverable = 1; 58702d1d418eSSumit Saxena 58712d1d418eSSumit Saxena return retval; 58722d1d418eSSumit Saxena } 58732d1d418eSSumit Saxena 58742d1d418eSSumit Saxena inline void mpi3mr_cleanup_event_taskq(struct mpi3mr_softc *sc) 58752d1d418eSSumit Saxena { 5876b411372bSWarner Losh /* 5877b411372bSWarner Losh * Block the taskqueue before draining. This means any new tasks won't 5878272a4060SWarner Losh * be queued to the taskqueue worker thread. But it doesn't stop the 5879272a4060SWarner Losh * current workers that are running. taskqueue_drain waits for those 5880272a4060SWarner Losh * correctly in the case of thread backed taskqueues. The while loop 5881272a4060SWarner Losh * ensures that all taskqueue threads have finished their current tasks. 5882b411372bSWarner Losh */ 58832d1d418eSSumit Saxena taskqueue_block(sc->cam_sc->ev_tq); 5884272a4060SWarner Losh while (taskqueue_cancel(sc->cam_sc->ev_tq, &sc->cam_sc->ev_task, NULL) != 0) { 5885b411372bSWarner Losh taskqueue_drain(sc->cam_sc->ev_tq, &sc->cam_sc->ev_task); 58862d1d418eSSumit Saxena } 5887272a4060SWarner Losh } 58882d1d418eSSumit Saxena 58892d1d418eSSumit Saxena /** 58902d1d418eSSumit Saxena * mpi3mr_soft_reset_handler - Reset the controller 58912d1d418eSSumit Saxena * @sc: Adapter instance reference 58922d1d418eSSumit Saxena * @reset_reason: Reset reason code 58932d1d418eSSumit Saxena * @snapdump: snapdump enable/disbale bit 58942d1d418eSSumit Saxena * 58952d1d418eSSumit Saxena * This is an handler for recovering controller by issuing soft 58962d1d418eSSumit Saxena * reset or diag fault reset. This is a blocking function and 58972d1d418eSSumit Saxena * when one reset is executed if any other resets they will be 58982d1d418eSSumit Saxena * blocked. All IOCTLs/IO will be blocked during the reset. If 58992d1d418eSSumit Saxena * controller reset is successful then the controller will be 59002d1d418eSSumit Saxena * reinitalized, otherwise the controller will be marked as not 59012d1d418eSSumit Saxena * recoverable 59022d1d418eSSumit Saxena * 59032d1d418eSSumit Saxena * Return: 0 on success, non-zero on failure. 59042d1d418eSSumit Saxena */ 59052d1d418eSSumit Saxena int mpi3mr_soft_reset_handler(struct mpi3mr_softc *sc, 59063012fa8fSChandrakanth patil U16 reset_reason, bool snapdump) 59072d1d418eSSumit Saxena { 59082d1d418eSSumit Saxena int retval = 0, i = 0; 59092d1d418eSSumit Saxena enum mpi3mr_iocstate ioc_state; 59102d1d418eSSumit Saxena 59112d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_INFO, "soft reset invoked: reason code: %s\n", 59122d1d418eSSumit Saxena mpi3mr_reset_rc_name(reset_reason)); 59132d1d418eSSumit Saxena 59142d1d418eSSumit Saxena if ((reset_reason == MPI3MR_RESET_FROM_IOCTL) && 59152d1d418eSSumit Saxena (sc->reset.ioctl_reset_snapdump != true)) 59162d1d418eSSumit Saxena snapdump = false; 59172d1d418eSSumit Saxena 59182d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_INFO, 59192d1d418eSSumit Saxena "soft_reset_handler: wait if diag save is in progress\n"); 59202d1d418eSSumit Saxena while (sc->diagsave_timeout) 59212d1d418eSSumit Saxena DELAY(1000 * 1000); 59222d1d418eSSumit Saxena 59232d1d418eSSumit Saxena ioc_state = mpi3mr_get_iocstate(sc); 59242d1d418eSSumit Saxena if (ioc_state == MRIOC_STATE_UNRECOVERABLE) { 59252d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_ERROR, "controller is in unrecoverable state, exit\n"); 59262d1d418eSSumit Saxena sc->reset.type = MPI3MR_NO_RESET; 59272d1d418eSSumit Saxena sc->reset.reason = MPI3MR_DEFAULT_RESET_REASON; 59282d1d418eSSumit Saxena sc->reset.status = -1; 59292d1d418eSSumit Saxena sc->reset.ioctl_reset_snapdump = false; 59302d1d418eSSumit Saxena return -1; 59312d1d418eSSumit Saxena } 59322d1d418eSSumit Saxena 59332d1d418eSSumit Saxena if (sc->reset_in_progress) { 59342d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_INFO, "reset is already in progress, exit\n"); 59352d1d418eSSumit Saxena return -1; 59362d1d418eSSumit Saxena } 59372d1d418eSSumit Saxena 59382d1d418eSSumit Saxena /* Pause IOs, drain and block the event taskqueue */ 59392d1d418eSSumit Saxena xpt_freeze_simq(sc->cam_sc->sim, 1); 59402d1d418eSSumit Saxena 59412d1d418eSSumit Saxena mpi3mr_cleanup_event_taskq(sc); 59422d1d418eSSumit Saxena 59432d1d418eSSumit Saxena sc->reset_in_progress = 1; 59442d1d418eSSumit Saxena sc->block_ioctls = 1; 59452d1d418eSSumit Saxena 59462d1d418eSSumit Saxena while (mpi3mr_atomic_read(&sc->pend_ioctls) && (i < PEND_IOCTLS_COMP_WAIT_TIME)) { 59472d1d418eSSumit Saxena ioc_state = mpi3mr_get_iocstate(sc); 59482d1d418eSSumit Saxena if (ioc_state == MRIOC_STATE_FAULT) 59492d1d418eSSumit Saxena break; 59502d1d418eSSumit Saxena i++; 59512d1d418eSSumit Saxena if (!(i % 5)) { 59522d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_INFO, 59532d1d418eSSumit Saxena "[%2ds]waiting for IOCTL to be finished from %s\n", i, __func__); 59542d1d418eSSumit Saxena } 59552d1d418eSSumit Saxena DELAY(1000 * 1000); 59562d1d418eSSumit Saxena } 59572d1d418eSSumit Saxena 59582d1d418eSSumit Saxena if ((!snapdump) && (reset_reason != MPI3MR_RESET_FROM_FAULT_WATCH) && 59592d1d418eSSumit Saxena (reset_reason != MPI3MR_RESET_FROM_FIRMWARE) && 59602d1d418eSSumit Saxena (reset_reason != MPI3MR_RESET_FROM_CIACTIV_FAULT)) { 59612d1d418eSSumit Saxena 59622d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_INFO, "Turn off events prior to reset\n"); 59632d1d418eSSumit Saxena 59642d1d418eSSumit Saxena for (i = 0; i < MPI3_EVENT_NOTIFY_EVENTMASK_WORDS; i++) 59652d1d418eSSumit Saxena sc->event_masks[i] = -1; 59662d1d418eSSumit Saxena mpi3mr_issue_event_notification(sc); 59672d1d418eSSumit Saxena } 59682d1d418eSSumit Saxena 59692d1d418eSSumit Saxena mpi3mr_disable_interrupts(sc); 59702d1d418eSSumit Saxena 59712d1d418eSSumit Saxena if (snapdump) 59722d1d418eSSumit Saxena mpi3mr_trigger_snapdump(sc, reset_reason); 59732d1d418eSSumit Saxena 59742d1d418eSSumit Saxena retval = mpi3mr_issue_reset(sc, 59752d1d418eSSumit Saxena MPI3_SYSIF_HOST_DIAG_RESET_ACTION_SOFT_RESET, reset_reason); 59762d1d418eSSumit Saxena if (retval) { 59772d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_ERROR, "Failed to issue soft reset to the ioc\n"); 59782d1d418eSSumit Saxena goto out; 59792d1d418eSSumit Saxena } 59802d1d418eSSumit Saxena 59812d1d418eSSumit Saxena mpi3mr_flush_drv_cmds(sc); 59822d1d418eSSumit Saxena mpi3mr_flush_io(sc); 59832d1d418eSSumit Saxena mpi3mr_invalidate_devhandles(sc); 59842d1d418eSSumit Saxena mpi3mr_memset_buffers(sc); 59852d1d418eSSumit Saxena 59862d1d418eSSumit Saxena if (sc->prepare_for_reset) { 59872d1d418eSSumit Saxena sc->prepare_for_reset = 0; 59882d1d418eSSumit Saxena sc->prepare_for_reset_timeout_counter = 0; 59892d1d418eSSumit Saxena } 59902d1d418eSSumit Saxena 59912d1d418eSSumit Saxena retval = mpi3mr_initialize_ioc(sc, MPI3MR_INIT_TYPE_RESET); 59922d1d418eSSumit Saxena if (retval) { 59932d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_ERROR, "reinit after soft reset failed: reason %d\n", 59942d1d418eSSumit Saxena reset_reason); 59952d1d418eSSumit Saxena goto out; 59962d1d418eSSumit Saxena } 59972d1d418eSSumit Saxena 59982d1d418eSSumit Saxena DELAY((1000 * 1000) * 10); 59992d1d418eSSumit Saxena out: 60002d1d418eSSumit Saxena if (!retval) { 60012d1d418eSSumit Saxena sc->diagsave_timeout = 0; 60022d1d418eSSumit Saxena sc->reset_in_progress = 0; 60032d1d418eSSumit Saxena mpi3mr_rfresh_tgtdevs(sc); 60042d1d418eSSumit Saxena sc->ts_update_counter = 0; 60052d1d418eSSumit Saxena sc->block_ioctls = 0; 60062d1d418eSSumit Saxena sc->pel_abort_requested = 0; 60072d1d418eSSumit Saxena if (sc->pel_wait_pend) { 60082d1d418eSSumit Saxena sc->pel_cmds.retry_count = 0; 60092d1d418eSSumit Saxena mpi3mr_issue_pel_wait(sc, &sc->pel_cmds); 60102d1d418eSSumit Saxena mpi3mr_app_send_aen(sc); 60112d1d418eSSumit Saxena } 60122d1d418eSSumit Saxena } else { 60132d1d418eSSumit Saxena mpi3mr_issue_reset(sc, 60142d1d418eSSumit Saxena MPI3_SYSIF_HOST_DIAG_RESET_ACTION_DIAG_FAULT, reset_reason); 60152d1d418eSSumit Saxena sc->unrecoverable = 1; 60162d1d418eSSumit Saxena sc->reset_in_progress = 0; 60172d1d418eSSumit Saxena } 60182d1d418eSSumit Saxena 60192d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_INFO, "Soft Reset: %s\n", ((retval == 0) ? "SUCCESS" : "FAILED")); 60202d1d418eSSumit Saxena 60212d1d418eSSumit Saxena taskqueue_unblock(sc->cam_sc->ev_tq); 60222d1d418eSSumit Saxena xpt_release_simq(sc->cam_sc->sim, 1); 60232d1d418eSSumit Saxena 60242d1d418eSSumit Saxena sc->reset.type = MPI3MR_NO_RESET; 60252d1d418eSSumit Saxena sc->reset.reason = MPI3MR_DEFAULT_RESET_REASON; 60262d1d418eSSumit Saxena sc->reset.status = retval; 60272d1d418eSSumit Saxena sc->reset.ioctl_reset_snapdump = false; 60282d1d418eSSumit Saxena 60292d1d418eSSumit Saxena return retval; 60302d1d418eSSumit Saxena } 60312d1d418eSSumit Saxena 60322d1d418eSSumit Saxena /** 60332d1d418eSSumit Saxena * mpi3mr_issue_ioc_shutdown - shutdown controller 60342d1d418eSSumit Saxena * @sc: Adapter instance reference 60352d1d418eSSumit Saxena * 60362d1d418eSSumit Saxena * Send shutodwn notification to the controller and wait for the 60372d1d418eSSumit Saxena * shutdown_timeout for it to be completed. 60382d1d418eSSumit Saxena * 60392d1d418eSSumit Saxena * Return: Nothing. 60402d1d418eSSumit Saxena */ 60412d1d418eSSumit Saxena static void mpi3mr_issue_ioc_shutdown(struct mpi3mr_softc *sc) 60422d1d418eSSumit Saxena { 60432d1d418eSSumit Saxena U32 ioc_config, ioc_status; 60442d1d418eSSumit Saxena U8 retval = 1, retry = 0; 60452d1d418eSSumit Saxena U32 timeout = MPI3MR_DEFAULT_SHUTDOWN_TIME * 10; 60462d1d418eSSumit Saxena 60472d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_INFO, "sending shutdown notification\n"); 60482d1d418eSSumit Saxena if (sc->unrecoverable) { 60492d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_ERROR, 60502d1d418eSSumit Saxena "controller is unrecoverable, shutdown not issued\n"); 60512d1d418eSSumit Saxena return; 60522d1d418eSSumit Saxena } 60532d1d418eSSumit Saxena ioc_status = mpi3mr_regread(sc, MPI3_SYSIF_IOC_STATUS_OFFSET); 60542d1d418eSSumit Saxena if ((ioc_status & MPI3_SYSIF_IOC_STATUS_SHUTDOWN_MASK) 60552d1d418eSSumit Saxena == MPI3_SYSIF_IOC_STATUS_SHUTDOWN_IN_PROGRESS) { 60562d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_ERROR, "shutdown already in progress\n"); 60572d1d418eSSumit Saxena return; 60582d1d418eSSumit Saxena } 60592d1d418eSSumit Saxena 60602d1d418eSSumit Saxena ioc_config = mpi3mr_regread(sc, MPI3_SYSIF_IOC_CONFIG_OFFSET); 60612d1d418eSSumit Saxena ioc_config |= MPI3_SYSIF_IOC_CONFIG_SHUTDOWN_NORMAL; 60622d1d418eSSumit Saxena ioc_config |= MPI3_SYSIF_IOC_CONFIG_DEVICE_SHUTDOWN_SEND_REQ; 60632d1d418eSSumit Saxena 60642d1d418eSSumit Saxena mpi3mr_regwrite(sc, MPI3_SYSIF_IOC_CONFIG_OFFSET, ioc_config); 60652d1d418eSSumit Saxena 60662d1d418eSSumit Saxena if (sc->facts.shutdown_timeout) 60672d1d418eSSumit Saxena timeout = sc->facts.shutdown_timeout * 10; 60682d1d418eSSumit Saxena 60692d1d418eSSumit Saxena do { 60702d1d418eSSumit Saxena ioc_status = mpi3mr_regread(sc, MPI3_SYSIF_IOC_STATUS_OFFSET); 60712d1d418eSSumit Saxena if ((ioc_status & MPI3_SYSIF_IOC_STATUS_SHUTDOWN_MASK) 60722d1d418eSSumit Saxena == MPI3_SYSIF_IOC_STATUS_SHUTDOWN_COMPLETE) { 60732d1d418eSSumit Saxena retval = 0; 60742d1d418eSSumit Saxena break; 60752d1d418eSSumit Saxena } 60762d1d418eSSumit Saxena 60772d1d418eSSumit Saxena if (sc->unrecoverable) 60782d1d418eSSumit Saxena break; 60792d1d418eSSumit Saxena 60802d1d418eSSumit Saxena if ((ioc_status & MPI3_SYSIF_IOC_STATUS_FAULT)) { 60812d1d418eSSumit Saxena mpi3mr_print_fault_info(sc); 60822d1d418eSSumit Saxena 60832d1d418eSSumit Saxena if (retry >= MPI3MR_MAX_SHUTDOWN_RETRY_COUNT) 60842d1d418eSSumit Saxena break; 60852d1d418eSSumit Saxena 60862d1d418eSSumit Saxena if (mpi3mr_issue_reset(sc, 60872d1d418eSSumit Saxena MPI3_SYSIF_HOST_DIAG_RESET_ACTION_SOFT_RESET, 60882d1d418eSSumit Saxena MPI3MR_RESET_FROM_CTLR_CLEANUP)) 60892d1d418eSSumit Saxena break; 60902d1d418eSSumit Saxena 60912d1d418eSSumit Saxena ioc_config = mpi3mr_regread(sc, MPI3_SYSIF_IOC_CONFIG_OFFSET); 60922d1d418eSSumit Saxena ioc_config |= MPI3_SYSIF_IOC_CONFIG_SHUTDOWN_NORMAL; 60932d1d418eSSumit Saxena ioc_config |= MPI3_SYSIF_IOC_CONFIG_DEVICE_SHUTDOWN_SEND_REQ; 60942d1d418eSSumit Saxena 60952d1d418eSSumit Saxena mpi3mr_regwrite(sc, MPI3_SYSIF_IOC_CONFIG_OFFSET, ioc_config); 60962d1d418eSSumit Saxena 60972d1d418eSSumit Saxena if (sc->facts.shutdown_timeout) 60982d1d418eSSumit Saxena timeout = sc->facts.shutdown_timeout * 10; 60992d1d418eSSumit Saxena 61002d1d418eSSumit Saxena retry++; 61012d1d418eSSumit Saxena } 61022d1d418eSSumit Saxena 61032d1d418eSSumit Saxena DELAY(100 * 1000); 61042d1d418eSSumit Saxena 61052d1d418eSSumit Saxena } while (--timeout); 61062d1d418eSSumit Saxena 61072d1d418eSSumit Saxena ioc_status = mpi3mr_regread(sc, MPI3_SYSIF_IOC_STATUS_OFFSET); 61082d1d418eSSumit Saxena ioc_config = mpi3mr_regread(sc, MPI3_SYSIF_IOC_CONFIG_OFFSET); 61092d1d418eSSumit Saxena 61102d1d418eSSumit Saxena if (retval) { 61112d1d418eSSumit Saxena if ((ioc_status & MPI3_SYSIF_IOC_STATUS_SHUTDOWN_MASK) 61122d1d418eSSumit Saxena == MPI3_SYSIF_IOC_STATUS_SHUTDOWN_IN_PROGRESS) 61132d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_ERROR, 61142d1d418eSSumit Saxena "shutdown still in progress after timeout\n"); 61152d1d418eSSumit Saxena } 61162d1d418eSSumit Saxena 61172d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_INFO, 61182d1d418eSSumit Saxena "ioc_status/ioc_config after %s shutdown is (0x%x)/(0x%x)\n", 61192d1d418eSSumit Saxena (!retval)?"successful":"failed", ioc_status, 61202d1d418eSSumit Saxena ioc_config); 61212d1d418eSSumit Saxena } 61222d1d418eSSumit Saxena 61232d1d418eSSumit Saxena /** 61242d1d418eSSumit Saxena * mpi3mr_cleanup_ioc - Cleanup controller 61252d1d418eSSumit Saxena * @sc: Adapter instance reference 61262d1d418eSSumit Saxena 61272d1d418eSSumit Saxena * controller cleanup handler, Message unit reset or soft reset 61282d1d418eSSumit Saxena * and shutdown notification is issued to the controller. 61292d1d418eSSumit Saxena * 61302d1d418eSSumit Saxena * Return: Nothing. 61312d1d418eSSumit Saxena */ 61322d1d418eSSumit Saxena void mpi3mr_cleanup_ioc(struct mpi3mr_softc *sc) 61332d1d418eSSumit Saxena { 61342d1d418eSSumit Saxena enum mpi3mr_iocstate ioc_state; 61352d1d418eSSumit Saxena 61362d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_INFO, "cleaning up the controller\n"); 61372d1d418eSSumit Saxena mpi3mr_disable_interrupts(sc); 61382d1d418eSSumit Saxena 61392d1d418eSSumit Saxena ioc_state = mpi3mr_get_iocstate(sc); 61402d1d418eSSumit Saxena 61412d1d418eSSumit Saxena if ((!sc->unrecoverable) && (!sc->reset_in_progress) && 61422d1d418eSSumit Saxena (ioc_state == MRIOC_STATE_READY)) { 61432d1d418eSSumit Saxena if (mpi3mr_mur_ioc(sc, 61442d1d418eSSumit Saxena MPI3MR_RESET_FROM_CTLR_CLEANUP)) 61452d1d418eSSumit Saxena mpi3mr_issue_reset(sc, 61462d1d418eSSumit Saxena MPI3_SYSIF_HOST_DIAG_RESET_ACTION_SOFT_RESET, 61472d1d418eSSumit Saxena MPI3MR_RESET_FROM_MUR_FAILURE); 61482d1d418eSSumit Saxena mpi3mr_issue_ioc_shutdown(sc); 61492d1d418eSSumit Saxena } 61502d1d418eSSumit Saxena 61512d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_INFO, "controller cleanup completed\n"); 61522d1d418eSSumit Saxena } 6153