12d1d418eSSumit Saxena /* 22d1d418eSSumit Saxena * SPDX-License-Identifier: BSD-2-Clause 32d1d418eSSumit Saxena * 42d1d418eSSumit Saxena * Copyright (c) 2016-2023, 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, 862d1d418eSSumit Saxena U32 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 1892d1d418eSSumit Saxena mpi3mr_trigger_snapdump(struct mpi3mr_softc *sc, U32 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 */ 2242d1d418eSSumit Saxena static void mpi3mr_check_rh_fault_ioc(struct mpi3mr_softc *sc, U32 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 */ 11702d1d418eSSumit Saxena static int mpi3mr_mur_ioc(struct mpi3mr_softc *sc, U32 reset_reason) 11712d1d418eSSumit Saxena { 11722d1d418eSSumit Saxena U32 ioc_config, timeout, ioc_status; 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); 11812d1d418eSSumit Saxena mpi3mr_regwrite(sc, MPI3_SYSIF_SCRATCHPAD0_OFFSET, reset_reason); 11822d1d418eSSumit Saxena ioc_config = mpi3mr_regread(sc, MPI3_SYSIF_IOC_CONFIG_OFFSET); 11832d1d418eSSumit Saxena ioc_config &= ~MPI3_SYSIF_IOC_CONFIG_ENABLE_IOC; 11842d1d418eSSumit Saxena mpi3mr_regwrite(sc, MPI3_SYSIF_IOC_CONFIG_OFFSET, ioc_config); 11852d1d418eSSumit Saxena 11862d1d418eSSumit Saxena timeout = MPI3MR_MUR_TIMEOUT * 10; 11872d1d418eSSumit Saxena do { 11882d1d418eSSumit Saxena ioc_status = mpi3mr_regread(sc, MPI3_SYSIF_IOC_STATUS_OFFSET); 11892d1d418eSSumit Saxena if ((ioc_status & MPI3_SYSIF_IOC_STATUS_RESET_HISTORY)) { 11902d1d418eSSumit Saxena mpi3mr_clear_resethistory(sc); 11912d1d418eSSumit Saxena ioc_config = 11922d1d418eSSumit Saxena mpi3mr_regread(sc, MPI3_SYSIF_IOC_CONFIG_OFFSET); 11932d1d418eSSumit Saxena if (!((ioc_status & MPI3_SYSIF_IOC_STATUS_READY) || 11942d1d418eSSumit Saxena (ioc_status & MPI3_SYSIF_IOC_STATUS_FAULT) || 11952d1d418eSSumit Saxena (ioc_config & MPI3_SYSIF_IOC_CONFIG_ENABLE_IOC))) { 11962d1d418eSSumit Saxena retval = 0; 11972d1d418eSSumit Saxena break; 11982d1d418eSSumit Saxena } 11992d1d418eSSumit Saxena } 12002d1d418eSSumit Saxena DELAY(100 * 1000); 12012d1d418eSSumit Saxena } while (--timeout); 12022d1d418eSSumit Saxena 12032d1d418eSSumit Saxena ioc_status = mpi3mr_regread(sc, MPI3_SYSIF_IOC_STATUS_OFFSET); 12042d1d418eSSumit Saxena ioc_config = mpi3mr_regread(sc, MPI3_SYSIF_IOC_CONFIG_OFFSET); 12052d1d418eSSumit Saxena 12062d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_INFO, "IOC Status/Config after %s MUR is (0x%x)/(0x%x)\n", 12072d1d418eSSumit Saxena !retval ? "successful":"failed", ioc_status, ioc_config); 12082d1d418eSSumit Saxena return retval; 12092d1d418eSSumit Saxena } 12102d1d418eSSumit Saxena 12112d1d418eSSumit Saxena /** 12122d1d418eSSumit Saxena * mpi3mr_bring_ioc_ready - Bring controller to ready state 12132d1d418eSSumit Saxena * @sc: Adapter instance reference 12142d1d418eSSumit Saxena * 12152d1d418eSSumit Saxena * Set Enable IOC bit in IOC configuration register and wait for 12162d1d418eSSumit Saxena * the controller to become ready. 12172d1d418eSSumit Saxena * 12182d1d418eSSumit Saxena * Return: 0 on success, appropriate error on failure. 12192d1d418eSSumit Saxena */ 12202d1d418eSSumit Saxena static int mpi3mr_bring_ioc_ready(struct mpi3mr_softc *sc) 12212d1d418eSSumit Saxena { 12222d1d418eSSumit Saxena U32 ioc_config, timeout; 12232d1d418eSSumit Saxena enum mpi3mr_iocstate current_state; 12242d1d418eSSumit Saxena 12252d1d418eSSumit Saxena ioc_config = mpi3mr_regread(sc, MPI3_SYSIF_IOC_CONFIG_OFFSET); 12262d1d418eSSumit Saxena ioc_config |= MPI3_SYSIF_IOC_CONFIG_ENABLE_IOC; 12272d1d418eSSumit Saxena mpi3mr_regwrite(sc, MPI3_SYSIF_IOC_CONFIG_OFFSET, ioc_config); 12282d1d418eSSumit Saxena 12292d1d418eSSumit Saxena timeout = sc->ready_timeout * 10; 12302d1d418eSSumit Saxena do { 12312d1d418eSSumit Saxena current_state = mpi3mr_get_iocstate(sc); 12322d1d418eSSumit Saxena if (current_state == MRIOC_STATE_READY) 12332d1d418eSSumit Saxena return 0; 12342d1d418eSSumit Saxena DELAY(100 * 1000); 12352d1d418eSSumit Saxena } while (--timeout); 12362d1d418eSSumit Saxena 12372d1d418eSSumit Saxena return -1; 12382d1d418eSSumit Saxena } 12392d1d418eSSumit Saxena 12402d1d418eSSumit Saxena static const struct { 12412d1d418eSSumit Saxena enum mpi3mr_iocstate value; 12422d1d418eSSumit Saxena char *name; 12432d1d418eSSumit Saxena } mrioc_states[] = { 12442d1d418eSSumit Saxena { MRIOC_STATE_READY, "ready" }, 12452d1d418eSSumit Saxena { MRIOC_STATE_FAULT, "fault" }, 12462d1d418eSSumit Saxena { MRIOC_STATE_RESET, "reset" }, 12472d1d418eSSumit Saxena { MRIOC_STATE_BECOMING_READY, "becoming ready" }, 12482d1d418eSSumit Saxena { MRIOC_STATE_RESET_REQUESTED, "reset requested" }, 12492d1d418eSSumit Saxena { MRIOC_STATE_COUNT, "Count" }, 12502d1d418eSSumit Saxena }; 12512d1d418eSSumit Saxena 12522d1d418eSSumit Saxena static const char *mpi3mr_iocstate_name(enum mpi3mr_iocstate mrioc_state) 12532d1d418eSSumit Saxena { 12542d1d418eSSumit Saxena int i; 12552d1d418eSSumit Saxena char *name = NULL; 12562d1d418eSSumit Saxena 12572d1d418eSSumit Saxena for (i = 0; i < MRIOC_STATE_COUNT; i++) { 12582d1d418eSSumit Saxena if (mrioc_states[i].value == mrioc_state){ 12592d1d418eSSumit Saxena name = mrioc_states[i].name; 12602d1d418eSSumit Saxena break; 12612d1d418eSSumit Saxena } 12622d1d418eSSumit Saxena } 12632d1d418eSSumit Saxena return name; 12642d1d418eSSumit Saxena } 12652d1d418eSSumit Saxena 12662d1d418eSSumit Saxena /* Reset reason to name mapper structure*/ 12672d1d418eSSumit Saxena static const struct { 12682d1d418eSSumit Saxena enum mpi3mr_reset_reason value; 12692d1d418eSSumit Saxena char *name; 12702d1d418eSSumit Saxena } mpi3mr_reset_reason_codes[] = { 12712d1d418eSSumit Saxena { MPI3MR_RESET_FROM_BRINGUP, "timeout in bringup" }, 12722d1d418eSSumit Saxena { MPI3MR_RESET_FROM_FAULT_WATCH, "fault" }, 12732d1d418eSSumit Saxena { MPI3MR_RESET_FROM_IOCTL, "application" }, 12742d1d418eSSumit Saxena { MPI3MR_RESET_FROM_EH_HOS, "error handling" }, 12752d1d418eSSumit Saxena { MPI3MR_RESET_FROM_TM_TIMEOUT, "TM timeout" }, 12762d1d418eSSumit Saxena { MPI3MR_RESET_FROM_IOCTL_TIMEOUT, "IOCTL timeout" }, 12772d1d418eSSumit Saxena { MPI3MR_RESET_FROM_SCSIIO_TIMEOUT, "SCSIIO timeout" }, 12782d1d418eSSumit Saxena { MPI3MR_RESET_FROM_MUR_FAILURE, "MUR failure" }, 12792d1d418eSSumit Saxena { MPI3MR_RESET_FROM_CTLR_CLEANUP, "timeout in controller cleanup" }, 12802d1d418eSSumit Saxena { MPI3MR_RESET_FROM_CIACTIV_FAULT, "component image activation fault" }, 12812d1d418eSSumit Saxena { MPI3MR_RESET_FROM_PE_TIMEOUT, "port enable timeout" }, 12822d1d418eSSumit Saxena { MPI3MR_RESET_FROM_TSU_TIMEOUT, "time stamp update timeout" }, 12832d1d418eSSumit Saxena { MPI3MR_RESET_FROM_DELREQQ_TIMEOUT, "delete request queue timeout" }, 12842d1d418eSSumit Saxena { MPI3MR_RESET_FROM_DELREPQ_TIMEOUT, "delete reply queue timeout" }, 12852d1d418eSSumit Saxena { 12862d1d418eSSumit Saxena MPI3MR_RESET_FROM_CREATEREPQ_TIMEOUT, 12872d1d418eSSumit Saxena "create request queue timeout" 12882d1d418eSSumit Saxena }, 12892d1d418eSSumit Saxena { 12902d1d418eSSumit Saxena MPI3MR_RESET_FROM_CREATEREQQ_TIMEOUT, 12912d1d418eSSumit Saxena "create reply queue timeout" 12922d1d418eSSumit Saxena }, 12932d1d418eSSumit Saxena { MPI3MR_RESET_FROM_IOCFACTS_TIMEOUT, "IOC facts timeout" }, 12942d1d418eSSumit Saxena { MPI3MR_RESET_FROM_IOCINIT_TIMEOUT, "IOC init timeout" }, 12952d1d418eSSumit Saxena { MPI3MR_RESET_FROM_EVTNOTIFY_TIMEOUT, "event notify timeout" }, 12962d1d418eSSumit Saxena { MPI3MR_RESET_FROM_EVTACK_TIMEOUT, "event acknowledgment timeout" }, 12972d1d418eSSumit Saxena { 12982d1d418eSSumit Saxena MPI3MR_RESET_FROM_CIACTVRST_TIMER, 12992d1d418eSSumit Saxena "component image activation timeout" 13002d1d418eSSumit Saxena }, 13012d1d418eSSumit Saxena { 13022d1d418eSSumit Saxena MPI3MR_RESET_FROM_GETPKGVER_TIMEOUT, 13032d1d418eSSumit Saxena "get package version timeout" 13042d1d418eSSumit Saxena }, 13052d1d418eSSumit Saxena { 13062d1d418eSSumit Saxena MPI3MR_RESET_FROM_PELABORT_TIMEOUT, 13072d1d418eSSumit Saxena "persistent event log abort timeout" 13082d1d418eSSumit Saxena }, 13092d1d418eSSumit Saxena { MPI3MR_RESET_FROM_SYSFS, "sysfs invocation" }, 13102d1d418eSSumit Saxena { MPI3MR_RESET_FROM_SYSFS_TIMEOUT, "sysfs TM timeout" }, 13112d1d418eSSumit Saxena { 13122d1d418eSSumit Saxena MPI3MR_RESET_FROM_DIAG_BUFFER_POST_TIMEOUT, 13132d1d418eSSumit Saxena "diagnostic buffer post timeout" 13142d1d418eSSumit Saxena }, 13152d1d418eSSumit Saxena { MPI3MR_RESET_FROM_FIRMWARE, "firmware asynchronus reset" }, 13162d1d418eSSumit Saxena { MPI3MR_RESET_REASON_COUNT, "Reset reason count" }, 13172d1d418eSSumit Saxena }; 13182d1d418eSSumit Saxena 13192d1d418eSSumit Saxena /** 13202d1d418eSSumit Saxena * mpi3mr_reset_rc_name - get reset reason code name 13212d1d418eSSumit Saxena * @reason_code: reset reason code value 13222d1d418eSSumit Saxena * 13232d1d418eSSumit Saxena * Map reset reason to an NULL terminated ASCII string 13242d1d418eSSumit Saxena * 13252d1d418eSSumit Saxena * Return: Name corresponding to reset reason value or NULL. 13262d1d418eSSumit Saxena */ 13272d1d418eSSumit Saxena static const char *mpi3mr_reset_rc_name(enum mpi3mr_reset_reason reason_code) 13282d1d418eSSumit Saxena { 13292d1d418eSSumit Saxena int i; 13302d1d418eSSumit Saxena char *name = NULL; 13312d1d418eSSumit Saxena 13322d1d418eSSumit Saxena for (i = 0; i < MPI3MR_RESET_REASON_COUNT; i++) { 13332d1d418eSSumit Saxena if (mpi3mr_reset_reason_codes[i].value == reason_code) { 13342d1d418eSSumit Saxena name = mpi3mr_reset_reason_codes[i].name; 13352d1d418eSSumit Saxena break; 13362d1d418eSSumit Saxena } 13372d1d418eSSumit Saxena } 13382d1d418eSSumit Saxena return name; 13392d1d418eSSumit Saxena } 13402d1d418eSSumit Saxena 13412d1d418eSSumit Saxena #define MAX_RESET_TYPE 3 13422d1d418eSSumit Saxena /* Reset type to name mapper structure*/ 13432d1d418eSSumit Saxena static const struct { 13442d1d418eSSumit Saxena U16 reset_type; 13452d1d418eSSumit Saxena char *name; 13462d1d418eSSumit Saxena } mpi3mr_reset_types[] = { 13472d1d418eSSumit Saxena { MPI3_SYSIF_HOST_DIAG_RESET_ACTION_SOFT_RESET, "soft" }, 13482d1d418eSSumit Saxena { MPI3_SYSIF_HOST_DIAG_RESET_ACTION_DIAG_FAULT, "diag fault" }, 13492d1d418eSSumit Saxena { MAX_RESET_TYPE, "count"} 13502d1d418eSSumit Saxena }; 13512d1d418eSSumit Saxena 13522d1d418eSSumit Saxena /** 13532d1d418eSSumit Saxena * mpi3mr_reset_type_name - get reset type name 13542d1d418eSSumit Saxena * @reset_type: reset type value 13552d1d418eSSumit Saxena * 13562d1d418eSSumit Saxena * Map reset type to an NULL terminated ASCII string 13572d1d418eSSumit Saxena * 13582d1d418eSSumit Saxena * Return: Name corresponding to reset type value or NULL. 13592d1d418eSSumit Saxena */ 13602d1d418eSSumit Saxena static const char *mpi3mr_reset_type_name(U16 reset_type) 13612d1d418eSSumit Saxena { 13622d1d418eSSumit Saxena int i; 13632d1d418eSSumit Saxena char *name = NULL; 13642d1d418eSSumit Saxena 13652d1d418eSSumit Saxena for (i = 0; i < MAX_RESET_TYPE; i++) { 13662d1d418eSSumit Saxena if (mpi3mr_reset_types[i].reset_type == reset_type) { 13672d1d418eSSumit Saxena name = mpi3mr_reset_types[i].name; 13682d1d418eSSumit Saxena break; 13692d1d418eSSumit Saxena } 13702d1d418eSSumit Saxena } 13712d1d418eSSumit Saxena return name; 13722d1d418eSSumit Saxena } 13732d1d418eSSumit Saxena 13742d1d418eSSumit Saxena /** 13752d1d418eSSumit Saxena * mpi3mr_soft_reset_success - Check softreset is success or not 13762d1d418eSSumit Saxena * @ioc_status: IOC status register value 13772d1d418eSSumit Saxena * @ioc_config: IOC config register value 13782d1d418eSSumit Saxena * 13792d1d418eSSumit Saxena * Check whether the soft reset is successful or not based on 13802d1d418eSSumit Saxena * IOC status and IOC config register values. 13812d1d418eSSumit Saxena * 13822d1d418eSSumit Saxena * Return: True when the soft reset is success, false otherwise. 13832d1d418eSSumit Saxena */ 13842d1d418eSSumit Saxena static inline bool 13852d1d418eSSumit Saxena mpi3mr_soft_reset_success(U32 ioc_status, U32 ioc_config) 13862d1d418eSSumit Saxena { 13872d1d418eSSumit Saxena if (!((ioc_status & MPI3_SYSIF_IOC_STATUS_READY) || 13882d1d418eSSumit Saxena (ioc_status & MPI3_SYSIF_IOC_STATUS_FAULT) || 13892d1d418eSSumit Saxena (ioc_config & MPI3_SYSIF_IOC_CONFIG_ENABLE_IOC))) 13902d1d418eSSumit Saxena return true; 13912d1d418eSSumit Saxena return false; 13922d1d418eSSumit Saxena } 13932d1d418eSSumit Saxena 13942d1d418eSSumit Saxena /** 13952d1d418eSSumit Saxena * mpi3mr_diagfault_success - Check diag fault is success or not 13962d1d418eSSumit Saxena * @sc: Adapter reference 13972d1d418eSSumit Saxena * @ioc_status: IOC status register value 13982d1d418eSSumit Saxena * 13992d1d418eSSumit Saxena * Check whether the controller hit diag reset fault code. 14002d1d418eSSumit Saxena * 14012d1d418eSSumit Saxena * Return: True when there is diag fault, false otherwise. 14022d1d418eSSumit Saxena */ 14032d1d418eSSumit Saxena static inline bool mpi3mr_diagfault_success(struct mpi3mr_softc *sc, 14042d1d418eSSumit Saxena U32 ioc_status) 14052d1d418eSSumit Saxena { 14062d1d418eSSumit Saxena U32 fault; 14072d1d418eSSumit Saxena 14082d1d418eSSumit Saxena if (!(ioc_status & MPI3_SYSIF_IOC_STATUS_FAULT)) 14092d1d418eSSumit Saxena return false; 14102d1d418eSSumit Saxena fault = mpi3mr_regread(sc, MPI3_SYSIF_FAULT_OFFSET) & MPI3_SYSIF_FAULT_CODE_MASK; 14112d1d418eSSumit Saxena if (fault == MPI3_SYSIF_FAULT_CODE_DIAG_FAULT_RESET) 14122d1d418eSSumit Saxena return true; 14132d1d418eSSumit Saxena return false; 14142d1d418eSSumit Saxena } 14152d1d418eSSumit Saxena 14162d1d418eSSumit Saxena /** 14172d1d418eSSumit Saxena * mpi3mr_issue_iocfacts - Send IOC Facts 14182d1d418eSSumit Saxena * @sc: Adapter instance reference 14192d1d418eSSumit Saxena * @facts_data: Cached IOC facts data 14202d1d418eSSumit Saxena * 14212d1d418eSSumit Saxena * Issue IOC Facts MPI request through admin queue and wait for 14222d1d418eSSumit Saxena * the completion of it or time out. 14232d1d418eSSumit Saxena * 14242d1d418eSSumit Saxena * Return: 0 on success, non-zero on failures. 14252d1d418eSSumit Saxena */ 14262d1d418eSSumit Saxena static int mpi3mr_issue_iocfacts(struct mpi3mr_softc *sc, 14272d1d418eSSumit Saxena Mpi3IOCFactsData_t *facts_data) 14282d1d418eSSumit Saxena { 14292d1d418eSSumit Saxena Mpi3IOCFactsRequest_t iocfacts_req; 14302d1d418eSSumit Saxena bus_dma_tag_t data_tag = NULL; 14312d1d418eSSumit Saxena bus_dmamap_t data_map = NULL; 14322d1d418eSSumit Saxena bus_addr_t data_phys = 0; 14332d1d418eSSumit Saxena void *data = NULL; 14342d1d418eSSumit Saxena U32 data_len = sizeof(*facts_data); 14352d1d418eSSumit Saxena int retval = 0; 14362d1d418eSSumit Saxena 14372d1d418eSSumit Saxena U8 sgl_flags = (MPI3_SGE_FLAGS_ELEMENT_TYPE_SIMPLE | 14382d1d418eSSumit Saxena MPI3_SGE_FLAGS_DLAS_SYSTEM | 14392d1d418eSSumit Saxena MPI3_SGE_FLAGS_END_OF_LIST); 14402d1d418eSSumit Saxena 14412d1d418eSSumit Saxena 144291d96135SWarner Losh /* 14431ec7c672SWarner Losh * We can't use sc->dma_loaddr here. We set those only after we get the 14441ec7c672SWarner Losh * iocfacts. So allocate in the lower 4GB. The amount of data is tiny 14451ec7c672SWarner Losh * and we don't do this that often, so any bouncing we might have to do 14461ec7c672SWarner Losh * isn't a cause for concern. 144791d96135SWarner Losh */ 14482d1d418eSSumit Saxena if (bus_dma_tag_create(sc->mpi3mr_parent_dmat, /* parent */ 14492d1d418eSSumit Saxena 4, 0, /* algnmnt, boundary */ 14502d1d418eSSumit Saxena BUS_SPACE_MAXADDR_32BIT,/* lowaddr */ 14512d1d418eSSumit Saxena BUS_SPACE_MAXADDR, /* highaddr */ 14522d1d418eSSumit Saxena NULL, NULL, /* filter, filterarg */ 14532d1d418eSSumit Saxena data_len, /* maxsize */ 14542d1d418eSSumit Saxena 1, /* nsegments */ 14552d1d418eSSumit Saxena data_len, /* maxsegsize */ 14562d1d418eSSumit Saxena 0, /* flags */ 14572d1d418eSSumit Saxena NULL, NULL, /* lockfunc, lockarg */ 14582d1d418eSSumit Saxena &data_tag)) { 14592d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_ERROR, "Cannot allocate request DMA tag\n"); 14602d1d418eSSumit Saxena return (ENOMEM); 14612d1d418eSSumit Saxena } 14622d1d418eSSumit Saxena 14632d1d418eSSumit Saxena if (bus_dmamem_alloc(data_tag, (void **)&data, 14642d1d418eSSumit Saxena BUS_DMA_NOWAIT, &data_map)) { 14652d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_ERROR, "Func: %s line: %d Data DMA mem alloc failed\n", 14662d1d418eSSumit Saxena __func__, __LINE__); 14672d1d418eSSumit Saxena return (ENOMEM); 14682d1d418eSSumit Saxena } 14692d1d418eSSumit Saxena 14702d1d418eSSumit Saxena bzero(data, data_len); 14712d1d418eSSumit Saxena bus_dmamap_load(data_tag, data_map, data, data_len, 147239a3e6a8SAlexander Motin mpi3mr_memaddr_cb, &data_phys, BUS_DMA_NOWAIT); 14732d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_XINFO, "Func: %s line: %d IOCfacts data phys addr= %#016jx size= %d\n", 14742d1d418eSSumit Saxena __func__, __LINE__, (uintmax_t)data_phys, data_len); 14752d1d418eSSumit Saxena 14762d1d418eSSumit Saxena if (!data) 14772d1d418eSSumit Saxena { 14782d1d418eSSumit Saxena retval = -1; 14792d1d418eSSumit Saxena printf(IOCNAME "Memory alloc for IOCFactsData: failed\n", 14802d1d418eSSumit Saxena sc->name); 14812d1d418eSSumit Saxena goto out; 14822d1d418eSSumit Saxena } 14832d1d418eSSumit Saxena 14842d1d418eSSumit Saxena mtx_lock(&sc->init_cmds.completion.lock); 14852d1d418eSSumit Saxena memset(&iocfacts_req, 0, sizeof(iocfacts_req)); 14862d1d418eSSumit Saxena 14872d1d418eSSumit Saxena if (sc->init_cmds.state & MPI3MR_CMD_PENDING) { 14882d1d418eSSumit Saxena retval = -1; 14892d1d418eSSumit Saxena printf(IOCNAME "Issue IOCFacts: Init command is in use\n", 14902d1d418eSSumit Saxena sc->name); 14912d1d418eSSumit Saxena mtx_unlock(&sc->init_cmds.completion.lock); 14922d1d418eSSumit Saxena goto out; 14932d1d418eSSumit Saxena } 14942d1d418eSSumit Saxena 14952d1d418eSSumit Saxena sc->init_cmds.state = MPI3MR_CMD_PENDING; 14962d1d418eSSumit Saxena sc->init_cmds.is_waiting = 1; 14972d1d418eSSumit Saxena sc->init_cmds.callback = NULL; 14982d1d418eSSumit Saxena iocfacts_req.HostTag = (MPI3MR_HOSTTAG_INITCMDS); 14992d1d418eSSumit Saxena iocfacts_req.Function = MPI3_FUNCTION_IOC_FACTS; 15002d1d418eSSumit Saxena 15012d1d418eSSumit Saxena mpi3mr_add_sg_single(&iocfacts_req.SGL, sgl_flags, data_len, 15022d1d418eSSumit Saxena data_phys); 15032d1d418eSSumit Saxena 15042d1d418eSSumit Saxena init_completion(&sc->init_cmds.completion); 15052d1d418eSSumit Saxena 15062d1d418eSSumit Saxena retval = mpi3mr_submit_admin_cmd(sc, &iocfacts_req, 15072d1d418eSSumit Saxena sizeof(iocfacts_req)); 15082d1d418eSSumit Saxena 15092d1d418eSSumit Saxena if (retval) { 15102d1d418eSSumit Saxena printf(IOCNAME "Issue IOCFacts: Admin Post failed\n", 15112d1d418eSSumit Saxena sc->name); 15122d1d418eSSumit Saxena goto out_unlock; 15132d1d418eSSumit Saxena } 15142d1d418eSSumit Saxena 15152d1d418eSSumit Saxena wait_for_completion_timeout(&sc->init_cmds.completion, 15162d1d418eSSumit Saxena (MPI3MR_INTADMCMD_TIMEOUT)); 15172d1d418eSSumit Saxena if (!(sc->init_cmds.state & MPI3MR_CMD_COMPLETE)) { 15182d1d418eSSumit Saxena printf(IOCNAME "Issue IOCFacts: command timed out\n", 15192d1d418eSSumit Saxena sc->name); 15202d1d418eSSumit Saxena mpi3mr_check_rh_fault_ioc(sc, 15212d1d418eSSumit Saxena MPI3MR_RESET_FROM_IOCFACTS_TIMEOUT); 15222d1d418eSSumit Saxena sc->unrecoverable = 1; 15232d1d418eSSumit Saxena retval = -1; 15242d1d418eSSumit Saxena goto out_unlock; 15252d1d418eSSumit Saxena } 15262d1d418eSSumit Saxena 15272d1d418eSSumit Saxena if ((sc->init_cmds.ioc_status & MPI3_IOCSTATUS_STATUS_MASK) 15282d1d418eSSumit Saxena != MPI3_IOCSTATUS_SUCCESS ) { 15292d1d418eSSumit Saxena printf(IOCNAME "Issue IOCFacts: Failed IOCStatus(0x%04x) " 15302d1d418eSSumit Saxena " Loginfo(0x%08x) \n" , sc->name, 15312d1d418eSSumit Saxena (sc->init_cmds.ioc_status & MPI3_IOCSTATUS_STATUS_MASK), 15322d1d418eSSumit Saxena sc->init_cmds.ioc_loginfo); 15332d1d418eSSumit Saxena retval = -1; 15342d1d418eSSumit Saxena goto out_unlock; 15352d1d418eSSumit Saxena } 15362d1d418eSSumit Saxena 15372d1d418eSSumit Saxena memcpy(facts_data, (U8 *)data, data_len); 15382d1d418eSSumit Saxena out_unlock: 15392d1d418eSSumit Saxena sc->init_cmds.state = MPI3MR_CMD_NOTUSED; 15402d1d418eSSumit Saxena mtx_unlock(&sc->init_cmds.completion.lock); 15412d1d418eSSumit Saxena 15422d1d418eSSumit Saxena out: 15432d1d418eSSumit Saxena if (data_phys != 0) 15442d1d418eSSumit Saxena bus_dmamap_unload(data_tag, data_map); 15452d1d418eSSumit Saxena if (data != NULL) 15462d1d418eSSumit Saxena bus_dmamem_free(data_tag, data, data_map); 15472d1d418eSSumit Saxena if (data_tag != NULL) 15482d1d418eSSumit Saxena bus_dma_tag_destroy(data_tag); 15492d1d418eSSumit Saxena return retval; 15502d1d418eSSumit Saxena } 15512d1d418eSSumit Saxena 15522d1d418eSSumit Saxena /** 15532d1d418eSSumit Saxena * mpi3mr_process_factsdata - Process IOC facts data 15542d1d418eSSumit Saxena * @sc: Adapter instance reference 15552d1d418eSSumit Saxena * @facts_data: Cached IOC facts data 15562d1d418eSSumit Saxena * 15572d1d418eSSumit Saxena * Convert IOC facts data into cpu endianness and cache it in 15582d1d418eSSumit Saxena * the driver . 15592d1d418eSSumit Saxena * 15602d1d418eSSumit Saxena * Return: Nothing. 15612d1d418eSSumit Saxena */ 15622d1d418eSSumit Saxena static int mpi3mr_process_factsdata(struct mpi3mr_softc *sc, 15632d1d418eSSumit Saxena Mpi3IOCFactsData_t *facts_data) 15642d1d418eSSumit Saxena { 15652d1d418eSSumit Saxena int retval = 0; 15662d1d418eSSumit Saxena U32 ioc_config, req_sz, facts_flags; 156728a27434SWarner Losh struct mpi3mr_compimg_ver *fwver; 15682d1d418eSSumit Saxena 15692d1d418eSSumit Saxena if (le16toh(facts_data->IOCFactsDataLength) != 15702d1d418eSSumit Saxena (sizeof(*facts_data) / 4)) { 15712d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_INFO, "IOCFacts data length mismatch " 15722d1d418eSSumit Saxena " driver_sz(%ld) firmware_sz(%d) \n", 15732d1d418eSSumit Saxena sizeof(*facts_data), 15742d1d418eSSumit Saxena facts_data->IOCFactsDataLength); 15752d1d418eSSumit Saxena } 15762d1d418eSSumit Saxena 15772d1d418eSSumit Saxena ioc_config = mpi3mr_regread(sc, MPI3_SYSIF_IOC_CONFIG_OFFSET); 15782d1d418eSSumit Saxena req_sz = 1 << ((ioc_config & MPI3_SYSIF_IOC_CONFIG_OPER_REQ_ENT_SZ) >> 15792d1d418eSSumit Saxena MPI3_SYSIF_IOC_CONFIG_OPER_REQ_ENT_SZ_SHIFT); 15802d1d418eSSumit Saxena 15812d1d418eSSumit Saxena if (facts_data->IOCRequestFrameSize != (req_sz/4)) { 15822d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_INFO, "IOCFacts data reqFrameSize mismatch " 15832d1d418eSSumit Saxena " hw_size(%d) firmware_sz(%d) \n" , req_sz/4, 15842d1d418eSSumit Saxena facts_data->IOCRequestFrameSize); 15852d1d418eSSumit Saxena } 15862d1d418eSSumit Saxena 15872d1d418eSSumit Saxena memset(&sc->facts, 0, sizeof(sc->facts)); 15882d1d418eSSumit Saxena 15892d1d418eSSumit Saxena facts_flags = le32toh(facts_data->Flags); 15902d1d418eSSumit Saxena sc->facts.op_req_sz = req_sz; 15912d1d418eSSumit Saxena sc->op_reply_sz = 1 << ((ioc_config & 15922d1d418eSSumit Saxena MPI3_SYSIF_IOC_CONFIG_OPER_RPY_ENT_SZ) >> 15932d1d418eSSumit Saxena MPI3_SYSIF_IOC_CONFIG_OPER_RPY_ENT_SZ_SHIFT); 15942d1d418eSSumit Saxena 15952d1d418eSSumit Saxena sc->facts.ioc_num = facts_data->IOCNumber; 15962d1d418eSSumit Saxena sc->facts.who_init = facts_data->WhoInit; 15972d1d418eSSumit Saxena sc->facts.max_msix_vectors = facts_data->MaxMSIxVectors; 15982d1d418eSSumit Saxena sc->facts.personality = (facts_flags & 15992d1d418eSSumit Saxena MPI3_IOCFACTS_FLAGS_PERSONALITY_MASK); 16002d1d418eSSumit Saxena sc->facts.dma_mask = (facts_flags & 16012d1d418eSSumit Saxena MPI3_IOCFACTS_FLAGS_DMA_ADDRESS_WIDTH_MASK) >> 16022d1d418eSSumit Saxena MPI3_IOCFACTS_FLAGS_DMA_ADDRESS_WIDTH_SHIFT; 16032d1d418eSSumit Saxena sc->facts.protocol_flags = facts_data->ProtocolFlags; 16042d1d418eSSumit Saxena sc->facts.mpi_version = (facts_data->MPIVersion.Word); 16052d1d418eSSumit Saxena sc->facts.max_reqs = (facts_data->MaxOutstandingRequests); 16062d1d418eSSumit Saxena sc->facts.product_id = (facts_data->ProductID); 16072d1d418eSSumit Saxena sc->facts.reply_sz = (facts_data->ReplyFrameSize) * 4; 16082d1d418eSSumit Saxena sc->facts.exceptions = (facts_data->IOCExceptions); 16092d1d418eSSumit Saxena sc->facts.max_perids = (facts_data->MaxPersistentID); 16102d1d418eSSumit Saxena sc->facts.max_vds = (facts_data->MaxVDs); 16112d1d418eSSumit Saxena sc->facts.max_hpds = (facts_data->MaxHostPDs); 16122d1d418eSSumit Saxena sc->facts.max_advhpds = (facts_data->MaxAdvHostPDs); 16132d1d418eSSumit Saxena sc->facts.max_raidpds = (facts_data->MaxRAIDPDs); 16142d1d418eSSumit Saxena sc->facts.max_nvme = (facts_data->MaxNVMe); 16152d1d418eSSumit Saxena sc->facts.max_pcieswitches = 16162d1d418eSSumit Saxena (facts_data->MaxPCIeSwitches); 16172d1d418eSSumit Saxena sc->facts.max_sasexpanders = 16182d1d418eSSumit Saxena (facts_data->MaxSASExpanders); 16192d1d418eSSumit Saxena sc->facts.max_sasinitiators = 16202d1d418eSSumit Saxena (facts_data->MaxSASInitiators); 16212d1d418eSSumit Saxena sc->facts.max_enclosures = (facts_data->MaxEnclosures); 16222d1d418eSSumit Saxena sc->facts.min_devhandle = (facts_data->MinDevHandle); 16232d1d418eSSumit Saxena sc->facts.max_devhandle = (facts_data->MaxDevHandle); 16242d1d418eSSumit Saxena sc->facts.max_op_req_q = 16252d1d418eSSumit Saxena (facts_data->MaxOperationalRequestQueues); 16262d1d418eSSumit Saxena sc->facts.max_op_reply_q = 16272d1d418eSSumit Saxena (facts_data->MaxOperationalReplyQueues); 16282d1d418eSSumit Saxena sc->facts.ioc_capabilities = 16292d1d418eSSumit Saxena (facts_data->IOCCapabilities); 16302d1d418eSSumit Saxena sc->facts.fw_ver.build_num = 16312d1d418eSSumit Saxena (facts_data->FWVersion.BuildNum); 16322d1d418eSSumit Saxena sc->facts.fw_ver.cust_id = 16332d1d418eSSumit Saxena (facts_data->FWVersion.CustomerID); 16342d1d418eSSumit Saxena sc->facts.fw_ver.ph_minor = facts_data->FWVersion.PhaseMinor; 16352d1d418eSSumit Saxena sc->facts.fw_ver.ph_major = facts_data->FWVersion.PhaseMajor; 16362d1d418eSSumit Saxena sc->facts.fw_ver.gen_minor = facts_data->FWVersion.GenMinor; 16372d1d418eSSumit Saxena sc->facts.fw_ver.gen_major = facts_data->FWVersion.GenMajor; 16382d1d418eSSumit Saxena sc->max_msix_vectors = min(sc->max_msix_vectors, 16392d1d418eSSumit Saxena sc->facts.max_msix_vectors); 16402d1d418eSSumit Saxena sc->facts.sge_mod_mask = facts_data->SGEModifierMask; 16412d1d418eSSumit Saxena sc->facts.sge_mod_value = facts_data->SGEModifierValue; 16422d1d418eSSumit Saxena sc->facts.sge_mod_shift = facts_data->SGEModifierShift; 16432d1d418eSSumit Saxena sc->facts.shutdown_timeout = 16442d1d418eSSumit Saxena (facts_data->ShutdownTimeout); 16452d1d418eSSumit Saxena sc->facts.max_dev_per_tg = facts_data->MaxDevicesPerThrottleGroup; 16462d1d418eSSumit Saxena sc->facts.io_throttle_data_length = 16472d1d418eSSumit Saxena facts_data->IOThrottleDataLength; 16482d1d418eSSumit Saxena sc->facts.max_io_throttle_group = 16492d1d418eSSumit Saxena facts_data->MaxIOThrottleGroup; 16502d1d418eSSumit Saxena sc->facts.io_throttle_low = facts_data->IOThrottleLow; 16512d1d418eSSumit Saxena sc->facts.io_throttle_high = facts_data->IOThrottleHigh; 16522d1d418eSSumit Saxena 16532d1d418eSSumit Saxena /*Store in 512b block count*/ 16542d1d418eSSumit Saxena if (sc->facts.io_throttle_data_length) 16552d1d418eSSumit Saxena sc->io_throttle_data_length = 16562d1d418eSSumit Saxena (sc->facts.io_throttle_data_length * 2 * 4); 16572d1d418eSSumit Saxena else 16582d1d418eSSumit Saxena /* set the length to 1MB + 1K to disable throttle*/ 16592d1d418eSSumit Saxena sc->io_throttle_data_length = MPI3MR_MAX_SECTORS + 2; 16602d1d418eSSumit Saxena 16612d1d418eSSumit Saxena sc->io_throttle_high = (sc->facts.io_throttle_high * 2 * 1024); 16622d1d418eSSumit Saxena sc->io_throttle_low = (sc->facts.io_throttle_low * 2 * 1024); 16632d1d418eSSumit Saxena 166428a27434SWarner Losh fwver = &sc->facts.fw_ver; 166528a27434SWarner Losh snprintf(sc->fw_version, sizeof(sc->fw_version), 166628a27434SWarner Losh "%d.%d.%d.%d.%05d-%05d", 166728a27434SWarner Losh fwver->gen_major, fwver->gen_minor, fwver->ph_major, 166828a27434SWarner Losh fwver->ph_minor, fwver->cust_id, fwver->build_num); 166928a27434SWarner Losh 16702d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_INFO, "ioc_num(%d), maxopQ(%d), maxopRepQ(%d), maxdh(%d)," 16712d1d418eSSumit Saxena "maxreqs(%d), mindh(%d) maxPDs(%d) maxvectors(%d) maxperids(%d)\n", 16722d1d418eSSumit Saxena sc->facts.ioc_num, sc->facts.max_op_req_q, 16732d1d418eSSumit Saxena sc->facts.max_op_reply_q, sc->facts.max_devhandle, 16742d1d418eSSumit Saxena sc->facts.max_reqs, sc->facts.min_devhandle, 16752d1d418eSSumit Saxena sc->facts.max_pds, sc->facts.max_msix_vectors, 16762d1d418eSSumit Saxena sc->facts.max_perids); 16772d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_INFO, "SGEModMask 0x%x SGEModVal 0x%x SGEModShift 0x%x\n", 16782d1d418eSSumit Saxena sc->facts.sge_mod_mask, sc->facts.sge_mod_value, 16792d1d418eSSumit Saxena sc->facts.sge_mod_shift); 16802d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_INFO, 16812d1d418eSSumit 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", 16822d1d418eSSumit Saxena sc->facts.max_dev_per_tg, sc->facts.max_io_throttle_group, 16832d1d418eSSumit Saxena sc->facts.io_throttle_data_length * 4, 16842d1d418eSSumit Saxena sc->facts.io_throttle_high, sc->facts.io_throttle_low); 16852d1d418eSSumit Saxena 16862d1d418eSSumit Saxena sc->max_host_ios = sc->facts.max_reqs - 16872d1d418eSSumit Saxena (MPI3MR_INTERNALCMDS_RESVD + 1); 16882d1d418eSSumit Saxena 168991d96135SWarner Losh /* 169091d96135SWarner Losh * Set the DMA mask for the card. dma_mask is the number of bits that 16911ec7c672SWarner Losh * can have bits set in them. Translate this into bus_dma loaddr args. 16921ec7c672SWarner Losh * Add sanity for more bits than address space or other overflow 169391d96135SWarner Losh * situations. 169491d96135SWarner Losh */ 169591d96135SWarner Losh if (sc->facts.dma_mask == 0 || 169691d96135SWarner Losh (sc->facts.dma_mask >= sizeof(bus_addr_t) * 8)) 169791d96135SWarner Losh sc->dma_loaddr = BUS_SPACE_MAXADDR; 169891d96135SWarner Losh else 169991d96135SWarner Losh sc->dma_loaddr = ~((1ull << sc->facts.dma_mask) - 1); 170091d96135SWarner Losh mpi3mr_dprint(sc, MPI3MR_INFO, 17011ec7c672SWarner Losh "dma_mask bits: %d loaddr 0x%jx\n", 17021ec7c672SWarner Losh sc->facts.dma_mask, sc->dma_loaddr); 170391d96135SWarner Losh 17042d1d418eSSumit Saxena return retval; 17052d1d418eSSumit Saxena } 17062d1d418eSSumit Saxena 17072d1d418eSSumit Saxena static inline void mpi3mr_setup_reply_free_queues(struct mpi3mr_softc *sc) 17082d1d418eSSumit Saxena { 17092d1d418eSSumit Saxena int i; 17102d1d418eSSumit Saxena bus_addr_t phys_addr; 17112d1d418eSSumit Saxena 17122d1d418eSSumit Saxena /* initialize Reply buffer Queue */ 17132d1d418eSSumit Saxena for (i = 0, phys_addr = sc->reply_buf_phys; 17142d1d418eSSumit Saxena i < sc->num_reply_bufs; i++, phys_addr += sc->reply_sz) 17152d1d418eSSumit Saxena sc->reply_free_q[i] = phys_addr; 17162d1d418eSSumit Saxena sc->reply_free_q[i] = (0); 17172d1d418eSSumit Saxena 17182d1d418eSSumit Saxena /* initialize Sense Buffer Queue */ 17192d1d418eSSumit Saxena for (i = 0, phys_addr = sc->sense_buf_phys; 17202d1d418eSSumit Saxena i < sc->num_sense_bufs; i++, phys_addr += MPI3MR_SENSEBUF_SZ) 17212d1d418eSSumit Saxena sc->sense_buf_q[i] = phys_addr; 17222d1d418eSSumit Saxena sc->sense_buf_q[i] = (0); 17232d1d418eSSumit Saxena 17242d1d418eSSumit Saxena } 17252d1d418eSSumit Saxena 17262d1d418eSSumit Saxena static int mpi3mr_reply_dma_alloc(struct mpi3mr_softc *sc) 17272d1d418eSSumit Saxena { 17282d1d418eSSumit Saxena U32 sz; 17292d1d418eSSumit Saxena 17302d1d418eSSumit Saxena sc->num_reply_bufs = sc->facts.max_reqs + MPI3MR_NUM_EVTREPLIES; 17312d1d418eSSumit Saxena sc->reply_free_q_sz = sc->num_reply_bufs + 1; 17322d1d418eSSumit Saxena sc->num_sense_bufs = sc->facts.max_reqs / MPI3MR_SENSEBUF_FACTOR; 17332d1d418eSSumit Saxena sc->sense_buf_q_sz = sc->num_sense_bufs + 1; 17342d1d418eSSumit Saxena 17352d1d418eSSumit Saxena sz = sc->num_reply_bufs * sc->reply_sz; 17362d1d418eSSumit Saxena 17372d1d418eSSumit Saxena if (bus_dma_tag_create(sc->mpi3mr_parent_dmat, /* parent */ 17382d1d418eSSumit Saxena 16, 0, /* algnmnt, boundary */ 1739ee7c431cSWarner Losh sc->dma_loaddr, /* lowaddr */ 17401ec7c672SWarner Losh BUS_SPACE_MAXADDR, /* highaddr */ 17412d1d418eSSumit Saxena NULL, NULL, /* filter, filterarg */ 17422d1d418eSSumit Saxena sz, /* maxsize */ 17432d1d418eSSumit Saxena 1, /* nsegments */ 17442d1d418eSSumit Saxena sz, /* maxsegsize */ 17452d1d418eSSumit Saxena 0, /* flags */ 17462d1d418eSSumit Saxena NULL, NULL, /* lockfunc, lockarg */ 17472d1d418eSSumit Saxena &sc->reply_buf_tag)) { 17482d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_ERROR, "Cannot allocate request DMA tag\n"); 17492d1d418eSSumit Saxena return (ENOMEM); 17502d1d418eSSumit Saxena } 17512d1d418eSSumit Saxena 17522d1d418eSSumit Saxena if (bus_dmamem_alloc(sc->reply_buf_tag, (void **)&sc->reply_buf, 17532d1d418eSSumit Saxena BUS_DMA_NOWAIT, &sc->reply_buf_dmamap)) { 17542d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_ERROR, "Func: %s line: %d DMA mem alloc failed\n", 17552d1d418eSSumit Saxena __func__, __LINE__); 17562d1d418eSSumit Saxena return (ENOMEM); 17572d1d418eSSumit Saxena } 17582d1d418eSSumit Saxena 17592d1d418eSSumit Saxena bzero(sc->reply_buf, sz); 17602d1d418eSSumit Saxena bus_dmamap_load(sc->reply_buf_tag, sc->reply_buf_dmamap, sc->reply_buf, sz, 176139a3e6a8SAlexander Motin mpi3mr_memaddr_cb, &sc->reply_buf_phys, BUS_DMA_NOWAIT); 17622d1d418eSSumit Saxena 17632d1d418eSSumit Saxena sc->reply_buf_dma_min_address = sc->reply_buf_phys; 17642d1d418eSSumit Saxena sc->reply_buf_dma_max_address = sc->reply_buf_phys + sz; 17652d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_XINFO, "reply buf (0x%p): depth(%d), frame_size(%d), " 17662d1d418eSSumit Saxena "pool_size(%d kB), reply_buf_dma(0x%llx)\n", 17672d1d418eSSumit Saxena sc->reply_buf, sc->num_reply_bufs, sc->reply_sz, 17682d1d418eSSumit Saxena (sz / 1024), (unsigned long long)sc->reply_buf_phys); 17692d1d418eSSumit Saxena 17702d1d418eSSumit Saxena /* reply free queue, 8 byte align */ 17712d1d418eSSumit Saxena sz = sc->reply_free_q_sz * 8; 17722d1d418eSSumit Saxena 17732d1d418eSSumit Saxena if (bus_dma_tag_create(sc->mpi3mr_parent_dmat, /* parent */ 17742d1d418eSSumit Saxena 8, 0, /* algnmnt, boundary */ 1775ee7c431cSWarner Losh sc->dma_loaddr, /* lowaddr */ 17761ec7c672SWarner Losh BUS_SPACE_MAXADDR, /* highaddr */ 17772d1d418eSSumit Saxena NULL, NULL, /* filter, filterarg */ 17782d1d418eSSumit Saxena sz, /* maxsize */ 17792d1d418eSSumit Saxena 1, /* nsegments */ 17802d1d418eSSumit Saxena sz, /* maxsegsize */ 17812d1d418eSSumit Saxena 0, /* flags */ 17822d1d418eSSumit Saxena NULL, NULL, /* lockfunc, lockarg */ 17832d1d418eSSumit Saxena &sc->reply_free_q_tag)) { 17842d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_ERROR, "Cannot allocate reply free queue DMA tag\n"); 17852d1d418eSSumit Saxena return (ENOMEM); 17862d1d418eSSumit Saxena } 17872d1d418eSSumit Saxena 17882d1d418eSSumit Saxena if (bus_dmamem_alloc(sc->reply_free_q_tag, (void **)&sc->reply_free_q, 17892d1d418eSSumit Saxena BUS_DMA_NOWAIT, &sc->reply_free_q_dmamap)) { 17902d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_ERROR, "Func: %s line: %d DMA mem alloc failed\n", 17912d1d418eSSumit Saxena __func__, __LINE__); 17922d1d418eSSumit Saxena return (ENOMEM); 17932d1d418eSSumit Saxena } 17942d1d418eSSumit Saxena 17952d1d418eSSumit Saxena bzero(sc->reply_free_q, sz); 17962d1d418eSSumit Saxena bus_dmamap_load(sc->reply_free_q_tag, sc->reply_free_q_dmamap, sc->reply_free_q, sz, 179739a3e6a8SAlexander Motin mpi3mr_memaddr_cb, &sc->reply_free_q_phys, BUS_DMA_NOWAIT); 17982d1d418eSSumit Saxena 17992d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_XINFO, "reply_free_q (0x%p): depth(%d), frame_size(%d), " 18002d1d418eSSumit Saxena "pool_size(%d kB), reply_free_q_dma(0x%llx)\n", 18012d1d418eSSumit Saxena sc->reply_free_q, sc->reply_free_q_sz, 8, (sz / 1024), 18022d1d418eSSumit Saxena (unsigned long long)sc->reply_free_q_phys); 18032d1d418eSSumit Saxena 18042d1d418eSSumit Saxena /* sense buffer pool, 4 byte align */ 18052d1d418eSSumit Saxena sz = sc->num_sense_bufs * MPI3MR_SENSEBUF_SZ; 18062d1d418eSSumit Saxena 18072d1d418eSSumit Saxena if (bus_dma_tag_create(sc->mpi3mr_parent_dmat, /* parent */ 18082d1d418eSSumit Saxena 4, 0, /* algnmnt, boundary */ 1809ee7c431cSWarner Losh sc->dma_loaddr, /* lowaddr */ 18101ec7c672SWarner Losh BUS_SPACE_MAXADDR, /* highaddr */ 18112d1d418eSSumit Saxena NULL, NULL, /* filter, filterarg */ 18122d1d418eSSumit Saxena sz, /* maxsize */ 18132d1d418eSSumit Saxena 1, /* nsegments */ 18142d1d418eSSumit Saxena sz, /* maxsegsize */ 18152d1d418eSSumit Saxena 0, /* flags */ 18162d1d418eSSumit Saxena NULL, NULL, /* lockfunc, lockarg */ 18172d1d418eSSumit Saxena &sc->sense_buf_tag)) { 18182d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_ERROR, "Cannot allocate Sense buffer DMA tag\n"); 18192d1d418eSSumit Saxena return (ENOMEM); 18202d1d418eSSumit Saxena } 18212d1d418eSSumit Saxena 18222d1d418eSSumit Saxena if (bus_dmamem_alloc(sc->sense_buf_tag, (void **)&sc->sense_buf, 18232d1d418eSSumit Saxena BUS_DMA_NOWAIT, &sc->sense_buf_dmamap)) { 18242d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_ERROR, "Func: %s line: %d DMA mem alloc failed\n", 18252d1d418eSSumit Saxena __func__, __LINE__); 18262d1d418eSSumit Saxena return (ENOMEM); 18272d1d418eSSumit Saxena } 18282d1d418eSSumit Saxena 18292d1d418eSSumit Saxena bzero(sc->sense_buf, sz); 18302d1d418eSSumit Saxena bus_dmamap_load(sc->sense_buf_tag, sc->sense_buf_dmamap, sc->sense_buf, sz, 183139a3e6a8SAlexander Motin mpi3mr_memaddr_cb, &sc->sense_buf_phys, BUS_DMA_NOWAIT); 18322d1d418eSSumit Saxena 18332d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_XINFO, "sense_buf (0x%p): depth(%d), frame_size(%d), " 18342d1d418eSSumit Saxena "pool_size(%d kB), sense_dma(0x%llx)\n", 18352d1d418eSSumit Saxena sc->sense_buf, sc->num_sense_bufs, MPI3MR_SENSEBUF_SZ, 18362d1d418eSSumit Saxena (sz / 1024), (unsigned long long)sc->sense_buf_phys); 18372d1d418eSSumit Saxena 18382d1d418eSSumit Saxena /* sense buffer queue, 8 byte align */ 18392d1d418eSSumit Saxena sz = sc->sense_buf_q_sz * 8; 18402d1d418eSSumit Saxena 18412d1d418eSSumit Saxena if (bus_dma_tag_create(sc->mpi3mr_parent_dmat, /* parent */ 18422d1d418eSSumit Saxena 8, 0, /* algnmnt, boundary */ 1843ee7c431cSWarner Losh sc->dma_loaddr, /* lowaddr */ 18441ec7c672SWarner Losh BUS_SPACE_MAXADDR, /* highaddr */ 18452d1d418eSSumit Saxena NULL, NULL, /* filter, filterarg */ 18462d1d418eSSumit Saxena sz, /* maxsize */ 18472d1d418eSSumit Saxena 1, /* nsegments */ 18482d1d418eSSumit Saxena sz, /* maxsegsize */ 18492d1d418eSSumit Saxena 0, /* flags */ 18502d1d418eSSumit Saxena NULL, NULL, /* lockfunc, lockarg */ 18512d1d418eSSumit Saxena &sc->sense_buf_q_tag)) { 18522d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_ERROR, "Cannot allocate Sense buffer Queue DMA tag\n"); 18532d1d418eSSumit Saxena return (ENOMEM); 18542d1d418eSSumit Saxena } 18552d1d418eSSumit Saxena 18562d1d418eSSumit Saxena if (bus_dmamem_alloc(sc->sense_buf_q_tag, (void **)&sc->sense_buf_q, 18572d1d418eSSumit Saxena BUS_DMA_NOWAIT, &sc->sense_buf_q_dmamap)) { 18582d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_ERROR, "Func: %s line: %d DMA mem alloc failed\n", 18592d1d418eSSumit Saxena __func__, __LINE__); 18602d1d418eSSumit Saxena return (ENOMEM); 18612d1d418eSSumit Saxena } 18622d1d418eSSumit Saxena 18632d1d418eSSumit Saxena bzero(sc->sense_buf_q, sz); 18642d1d418eSSumit Saxena bus_dmamap_load(sc->sense_buf_q_tag, sc->sense_buf_q_dmamap, sc->sense_buf_q, sz, 186539a3e6a8SAlexander Motin mpi3mr_memaddr_cb, &sc->sense_buf_q_phys, BUS_DMA_NOWAIT); 18662d1d418eSSumit Saxena 18672d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_XINFO, "sense_buf_q (0x%p): depth(%d), frame_size(%d), " 18682d1d418eSSumit Saxena "pool_size(%d kB), sense_dma(0x%llx)\n", 18692d1d418eSSumit Saxena sc->sense_buf_q, sc->sense_buf_q_sz, 8, (sz / 1024), 18702d1d418eSSumit Saxena (unsigned long long)sc->sense_buf_q_phys); 18712d1d418eSSumit Saxena 18722d1d418eSSumit Saxena return 0; 18732d1d418eSSumit Saxena } 18742d1d418eSSumit Saxena 18752d1d418eSSumit Saxena static int mpi3mr_reply_alloc(struct mpi3mr_softc *sc) 18762d1d418eSSumit Saxena { 18772d1d418eSSumit Saxena int retval = 0; 18782d1d418eSSumit Saxena U32 i; 18792d1d418eSSumit Saxena 18802d1d418eSSumit Saxena if (sc->init_cmds.reply) 18812d1d418eSSumit Saxena goto post_reply_sbuf; 18822d1d418eSSumit Saxena 18832d1d418eSSumit Saxena sc->init_cmds.reply = malloc(sc->reply_sz, 18842d1d418eSSumit Saxena M_MPI3MR, M_NOWAIT | M_ZERO); 18852d1d418eSSumit Saxena 18862d1d418eSSumit Saxena if (!sc->init_cmds.reply) { 18872d1d418eSSumit Saxena printf(IOCNAME "Cannot allocate memory for init_cmds.reply\n", 18882d1d418eSSumit Saxena sc->name); 18892d1d418eSSumit Saxena goto out_failed; 18902d1d418eSSumit Saxena } 18912d1d418eSSumit Saxena 18922d1d418eSSumit Saxena sc->ioctl_cmds.reply = malloc(sc->reply_sz, M_MPI3MR, M_NOWAIT | M_ZERO); 18932d1d418eSSumit Saxena if (!sc->ioctl_cmds.reply) { 18942d1d418eSSumit Saxena printf(IOCNAME "Cannot allocate memory for ioctl_cmds.reply\n", 18952d1d418eSSumit Saxena sc->name); 18962d1d418eSSumit Saxena goto out_failed; 18972d1d418eSSumit Saxena } 18982d1d418eSSumit Saxena 18992d1d418eSSumit Saxena sc->host_tm_cmds.reply = malloc(sc->reply_sz, M_MPI3MR, M_NOWAIT | M_ZERO); 19002d1d418eSSumit Saxena if (!sc->host_tm_cmds.reply) { 19012d1d418eSSumit Saxena printf(IOCNAME "Cannot allocate memory for host_tm.reply\n", 19022d1d418eSSumit Saxena sc->name); 19032d1d418eSSumit Saxena goto out_failed; 19042d1d418eSSumit Saxena } 19052d1d418eSSumit Saxena for (i=0; i<MPI3MR_NUM_DEVRMCMD; i++) { 19062d1d418eSSumit Saxena sc->dev_rmhs_cmds[i].reply = malloc(sc->reply_sz, 19072d1d418eSSumit Saxena M_MPI3MR, M_NOWAIT | M_ZERO); 19082d1d418eSSumit Saxena if (!sc->dev_rmhs_cmds[i].reply) { 19092d1d418eSSumit Saxena printf(IOCNAME "Cannot allocate memory for" 19102d1d418eSSumit Saxena " dev_rmhs_cmd[%d].reply\n", 19112d1d418eSSumit Saxena sc->name, i); 19122d1d418eSSumit Saxena goto out_failed; 19132d1d418eSSumit Saxena } 19142d1d418eSSumit Saxena } 19152d1d418eSSumit Saxena 19162d1d418eSSumit Saxena for (i = 0; i < MPI3MR_NUM_EVTACKCMD; i++) { 19172d1d418eSSumit Saxena sc->evtack_cmds[i].reply = malloc(sc->reply_sz, 19182d1d418eSSumit Saxena M_MPI3MR, M_NOWAIT | M_ZERO); 19192d1d418eSSumit Saxena if (!sc->evtack_cmds[i].reply) 19202d1d418eSSumit Saxena goto out_failed; 19212d1d418eSSumit Saxena } 19222d1d418eSSumit Saxena 19232d1d418eSSumit Saxena sc->dev_handle_bitmap_sz = MPI3MR_DIV_ROUND_UP(sc->facts.max_devhandle, 8); 19242d1d418eSSumit Saxena 19252d1d418eSSumit Saxena sc->removepend_bitmap = malloc(sc->dev_handle_bitmap_sz, 19262d1d418eSSumit Saxena M_MPI3MR, M_NOWAIT | M_ZERO); 19272d1d418eSSumit Saxena if (!sc->removepend_bitmap) { 19282d1d418eSSumit Saxena printf(IOCNAME "Cannot alloc memory for remove pend bitmap\n", 19292d1d418eSSumit Saxena sc->name); 19302d1d418eSSumit Saxena goto out_failed; 19312d1d418eSSumit Saxena } 19322d1d418eSSumit Saxena 19332d1d418eSSumit Saxena sc->devrem_bitmap_sz = MPI3MR_DIV_ROUND_UP(MPI3MR_NUM_DEVRMCMD, 8); 19342d1d418eSSumit Saxena sc->devrem_bitmap = malloc(sc->devrem_bitmap_sz, 19352d1d418eSSumit Saxena M_MPI3MR, M_NOWAIT | M_ZERO); 19362d1d418eSSumit Saxena if (!sc->devrem_bitmap) { 19372d1d418eSSumit Saxena printf(IOCNAME "Cannot alloc memory for dev remove bitmap\n", 19382d1d418eSSumit Saxena sc->name); 19392d1d418eSSumit Saxena goto out_failed; 19402d1d418eSSumit Saxena } 19412d1d418eSSumit Saxena 19422d1d418eSSumit Saxena sc->evtack_cmds_bitmap_sz = MPI3MR_DIV_ROUND_UP(MPI3MR_NUM_EVTACKCMD, 8); 19432d1d418eSSumit Saxena 19442d1d418eSSumit Saxena sc->evtack_cmds_bitmap = malloc(sc->evtack_cmds_bitmap_sz, 19452d1d418eSSumit Saxena M_MPI3MR, M_NOWAIT | M_ZERO); 19462d1d418eSSumit Saxena if (!sc->evtack_cmds_bitmap) 19472d1d418eSSumit Saxena goto out_failed; 19482d1d418eSSumit Saxena 19492d1d418eSSumit Saxena if (mpi3mr_reply_dma_alloc(sc)) { 19502d1d418eSSumit Saxena printf(IOCNAME "func:%s line:%d DMA memory allocation failed\n", 19512d1d418eSSumit Saxena sc->name, __func__, __LINE__); 19522d1d418eSSumit Saxena goto out_failed; 19532d1d418eSSumit Saxena } 19542d1d418eSSumit Saxena 19552d1d418eSSumit Saxena post_reply_sbuf: 19562d1d418eSSumit Saxena mpi3mr_setup_reply_free_queues(sc); 19572d1d418eSSumit Saxena return retval; 19582d1d418eSSumit Saxena out_failed: 19592d1d418eSSumit Saxena mpi3mr_cleanup_interrupts(sc); 19602d1d418eSSumit Saxena mpi3mr_free_mem(sc); 19612d1d418eSSumit Saxena retval = -1; 19622d1d418eSSumit Saxena return retval; 19632d1d418eSSumit Saxena } 19642d1d418eSSumit Saxena 19652d1d418eSSumit Saxena static void 19662d1d418eSSumit Saxena mpi3mr_print_fw_pkg_ver(struct mpi3mr_softc *sc) 19672d1d418eSSumit Saxena { 19682d1d418eSSumit Saxena int retval = 0; 19692d1d418eSSumit Saxena void *fw_pkg_ver = NULL; 19702d1d418eSSumit Saxena bus_dma_tag_t fw_pkg_ver_tag; 19712d1d418eSSumit Saxena bus_dmamap_t fw_pkg_ver_map; 19722d1d418eSSumit Saxena bus_addr_t fw_pkg_ver_dma; 19732d1d418eSSumit Saxena Mpi3CIUploadRequest_t ci_upload; 19742d1d418eSSumit Saxena Mpi3ComponentImageHeader_t *ci_header; 19752d1d418eSSumit Saxena U32 fw_pkg_ver_len = sizeof(*ci_header); 19762d1d418eSSumit Saxena U8 sgl_flags = MPI3MR_SGEFLAGS_SYSTEM_SIMPLE_END_OF_LIST; 19772d1d418eSSumit Saxena 19782d1d418eSSumit Saxena if (bus_dma_tag_create(sc->mpi3mr_parent_dmat, /* parent */ 19792d1d418eSSumit Saxena 4, 0, /* algnmnt, boundary */ 1980ee7c431cSWarner Losh sc->dma_loaddr, /* lowaddr */ 19811ec7c672SWarner Losh BUS_SPACE_MAXADDR, /* highaddr */ 19822d1d418eSSumit Saxena NULL, NULL, /* filter, filterarg */ 19832d1d418eSSumit Saxena fw_pkg_ver_len, /* maxsize */ 19842d1d418eSSumit Saxena 1, /* nsegments */ 19852d1d418eSSumit Saxena fw_pkg_ver_len, /* maxsegsize */ 19862d1d418eSSumit Saxena 0, /* flags */ 19872d1d418eSSumit Saxena NULL, NULL, /* lockfunc, lockarg */ 19882d1d418eSSumit Saxena &fw_pkg_ver_tag)) { 19892d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_ERROR, "Cannot allocate fw package version request DMA tag\n"); 19902d1d418eSSumit Saxena return; 19912d1d418eSSumit Saxena } 19922d1d418eSSumit Saxena 19932d1d418eSSumit Saxena if (bus_dmamem_alloc(fw_pkg_ver_tag, (void **)&fw_pkg_ver, BUS_DMA_NOWAIT, &fw_pkg_ver_map)) { 19942d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_ERROR, "Func: %s line: %d fw package version DMA mem alloc failed\n", 19952d1d418eSSumit Saxena __func__, __LINE__); 19962d1d418eSSumit Saxena return; 19972d1d418eSSumit Saxena } 19982d1d418eSSumit Saxena 19992d1d418eSSumit Saxena bzero(fw_pkg_ver, fw_pkg_ver_len); 20002d1d418eSSumit Saxena 200139a3e6a8SAlexander Motin bus_dmamap_load(fw_pkg_ver_tag, fw_pkg_ver_map, fw_pkg_ver, fw_pkg_ver_len, 200239a3e6a8SAlexander Motin mpi3mr_memaddr_cb, &fw_pkg_ver_dma, BUS_DMA_NOWAIT); 20032d1d418eSSumit Saxena 20042d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_XINFO, "Func: %s line: %d fw package version phys addr= %#016jx size= %d\n", 20052d1d418eSSumit Saxena __func__, __LINE__, (uintmax_t)fw_pkg_ver_dma, fw_pkg_ver_len); 20062d1d418eSSumit Saxena 20072d1d418eSSumit Saxena if (!fw_pkg_ver) { 20082d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_ERROR, "Memory alloc for fw package version failed\n"); 20092d1d418eSSumit Saxena goto out; 20102d1d418eSSumit Saxena } 20112d1d418eSSumit Saxena 20122d1d418eSSumit Saxena memset(&ci_upload, 0, sizeof(ci_upload)); 20132d1d418eSSumit Saxena mtx_lock(&sc->init_cmds.completion.lock); 20142d1d418eSSumit Saxena if (sc->init_cmds.state & MPI3MR_CMD_PENDING) { 20152d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_INFO,"Issue CI Header Upload: command is in use\n"); 20162d1d418eSSumit Saxena mtx_unlock(&sc->init_cmds.completion.lock); 20172d1d418eSSumit Saxena goto out; 20182d1d418eSSumit Saxena } 20192d1d418eSSumit Saxena sc->init_cmds.state = MPI3MR_CMD_PENDING; 20202d1d418eSSumit Saxena sc->init_cmds.is_waiting = 1; 20212d1d418eSSumit Saxena sc->init_cmds.callback = NULL; 20222d1d418eSSumit Saxena ci_upload.HostTag = htole16(MPI3MR_HOSTTAG_INITCMDS); 20232d1d418eSSumit Saxena ci_upload.Function = MPI3_FUNCTION_CI_UPLOAD; 20242d1d418eSSumit Saxena ci_upload.MsgFlags = MPI3_CI_UPLOAD_MSGFLAGS_LOCATION_PRIMARY; 20252d1d418eSSumit Saxena ci_upload.ImageOffset = MPI3_IMAGE_HEADER_SIGNATURE0_OFFSET; 20262d1d418eSSumit Saxena ci_upload.SegmentSize = MPI3_IMAGE_HEADER_SIZE; 20272d1d418eSSumit Saxena 20282d1d418eSSumit Saxena mpi3mr_add_sg_single(&ci_upload.SGL, sgl_flags, fw_pkg_ver_len, 20292d1d418eSSumit Saxena fw_pkg_ver_dma); 20302d1d418eSSumit Saxena 20312d1d418eSSumit Saxena init_completion(&sc->init_cmds.completion); 20322d1d418eSSumit Saxena if ((retval = mpi3mr_submit_admin_cmd(sc, &ci_upload, sizeof(ci_upload)))) { 20332d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_ERROR, "Issue CI Header Upload: Admin Post failed\n"); 20342d1d418eSSumit Saxena goto out_unlock; 20352d1d418eSSumit Saxena } 20362d1d418eSSumit Saxena wait_for_completion_timeout(&sc->init_cmds.completion, 20372d1d418eSSumit Saxena (MPI3MR_INTADMCMD_TIMEOUT)); 20382d1d418eSSumit Saxena if (!(sc->init_cmds.state & MPI3MR_CMD_COMPLETE)) { 20392d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_ERROR, "Issue CI Header Upload: command timed out\n"); 20402d1d418eSSumit Saxena sc->init_cmds.is_waiting = 0; 20412d1d418eSSumit Saxena if (!(sc->init_cmds.state & MPI3MR_CMD_RESET)) 20422d1d418eSSumit Saxena mpi3mr_check_rh_fault_ioc(sc, 20432d1d418eSSumit Saxena MPI3MR_RESET_FROM_GETPKGVER_TIMEOUT); 20442d1d418eSSumit Saxena goto out_unlock; 20452d1d418eSSumit Saxena } 20462d1d418eSSumit Saxena if ((GET_IOC_STATUS(sc->init_cmds.ioc_status)) != MPI3_IOCSTATUS_SUCCESS) { 20472d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_ERROR, 20482d1d418eSSumit Saxena "Issue CI Header Upload: Failed IOCStatus(0x%04x) Loginfo(0x%08x)\n", 20492d1d418eSSumit Saxena GET_IOC_STATUS(sc->init_cmds.ioc_status), sc->init_cmds.ioc_loginfo); 20502d1d418eSSumit Saxena goto out_unlock; 20512d1d418eSSumit Saxena } 20522d1d418eSSumit Saxena 20532d1d418eSSumit Saxena ci_header = (Mpi3ComponentImageHeader_t *) fw_pkg_ver; 20542d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_XINFO, 20552d1d418eSSumit Saxena "Issue CI Header Upload:EnvVariableOffset(0x%x) \ 20562d1d418eSSumit Saxena HeaderSize(0x%x) Signature1(0x%x)\n", 20572d1d418eSSumit Saxena ci_header->EnvironmentVariableOffset, 20582d1d418eSSumit Saxena ci_header->HeaderSize, 20592d1d418eSSumit Saxena ci_header->Signature1); 20602d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_INFO, "FW Package Version: %02d.%02d.%02d.%02d\n", 20612d1d418eSSumit Saxena ci_header->ComponentImageVersion.GenMajor, 20622d1d418eSSumit Saxena ci_header->ComponentImageVersion.GenMinor, 20632d1d418eSSumit Saxena ci_header->ComponentImageVersion.PhaseMajor, 20642d1d418eSSumit Saxena ci_header->ComponentImageVersion.PhaseMinor); 20652d1d418eSSumit Saxena out_unlock: 20662d1d418eSSumit Saxena sc->init_cmds.state = MPI3MR_CMD_NOTUSED; 20672d1d418eSSumit Saxena mtx_unlock(&sc->init_cmds.completion.lock); 20682d1d418eSSumit Saxena 20692d1d418eSSumit Saxena out: 20702d1d418eSSumit Saxena if (fw_pkg_ver_dma != 0) 20712d1d418eSSumit Saxena bus_dmamap_unload(fw_pkg_ver_tag, fw_pkg_ver_map); 20722d1d418eSSumit Saxena if (fw_pkg_ver) 20732d1d418eSSumit Saxena bus_dmamem_free(fw_pkg_ver_tag, fw_pkg_ver, fw_pkg_ver_map); 20742d1d418eSSumit Saxena if (fw_pkg_ver_tag) 20752d1d418eSSumit Saxena bus_dma_tag_destroy(fw_pkg_ver_tag); 20762d1d418eSSumit Saxena 20772d1d418eSSumit Saxena } 20782d1d418eSSumit Saxena 20792d1d418eSSumit Saxena /** 20802d1d418eSSumit Saxena * mpi3mr_issue_iocinit - Send IOC Init 20812d1d418eSSumit Saxena * @sc: Adapter instance reference 20822d1d418eSSumit Saxena * 20832d1d418eSSumit Saxena * Issue IOC Init MPI request through admin queue and wait for 20842d1d418eSSumit Saxena * the completion of it or time out. 20852d1d418eSSumit Saxena * 20862d1d418eSSumit Saxena * Return: 0 on success, non-zero on failures. 20872d1d418eSSumit Saxena */ 20882d1d418eSSumit Saxena static int mpi3mr_issue_iocinit(struct mpi3mr_softc *sc) 20892d1d418eSSumit Saxena { 20902d1d418eSSumit Saxena Mpi3IOCInitRequest_t iocinit_req; 20912d1d418eSSumit Saxena Mpi3DriverInfoLayout_t *drvr_info = NULL; 20922d1d418eSSumit Saxena bus_dma_tag_t drvr_info_tag; 20932d1d418eSSumit Saxena bus_dmamap_t drvr_info_map; 20942d1d418eSSumit Saxena bus_addr_t drvr_info_phys; 20952d1d418eSSumit Saxena U32 drvr_info_len = sizeof(*drvr_info); 20962d1d418eSSumit Saxena int retval = 0; 20972d1d418eSSumit Saxena struct timeval now; 20982d1d418eSSumit Saxena uint64_t time_in_msec; 20992d1d418eSSumit Saxena 21002d1d418eSSumit Saxena if (bus_dma_tag_create(sc->mpi3mr_parent_dmat, /* parent */ 21012d1d418eSSumit Saxena 4, 0, /* algnmnt, boundary */ 2102ee7c431cSWarner Losh sc->dma_loaddr, /* lowaddr */ 21031ec7c672SWarner Losh BUS_SPACE_MAXADDR, /* highaddr */ 21042d1d418eSSumit Saxena NULL, NULL, /* filter, filterarg */ 21052d1d418eSSumit Saxena drvr_info_len, /* maxsize */ 21062d1d418eSSumit Saxena 1, /* nsegments */ 21072d1d418eSSumit Saxena drvr_info_len, /* maxsegsize */ 21082d1d418eSSumit Saxena 0, /* flags */ 21092d1d418eSSumit Saxena NULL, NULL, /* lockfunc, lockarg */ 21102d1d418eSSumit Saxena &drvr_info_tag)) { 21112d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_ERROR, "Cannot allocate request DMA tag\n"); 21122d1d418eSSumit Saxena return (ENOMEM); 21132d1d418eSSumit Saxena } 21142d1d418eSSumit Saxena 21152d1d418eSSumit Saxena if (bus_dmamem_alloc(drvr_info_tag, (void **)&drvr_info, 21162d1d418eSSumit Saxena BUS_DMA_NOWAIT, &drvr_info_map)) { 21172d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_ERROR, "Func: %s line: %d Data DMA mem alloc failed\n", 21182d1d418eSSumit Saxena __func__, __LINE__); 21192d1d418eSSumit Saxena return (ENOMEM); 21202d1d418eSSumit Saxena } 21212d1d418eSSumit Saxena 21222d1d418eSSumit Saxena bzero(drvr_info, drvr_info_len); 21232d1d418eSSumit Saxena bus_dmamap_load(drvr_info_tag, drvr_info_map, drvr_info, drvr_info_len, 212439a3e6a8SAlexander Motin mpi3mr_memaddr_cb, &drvr_info_phys, BUS_DMA_NOWAIT); 21252d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_XINFO, "Func: %s line: %d IOCfacts drvr_info phys addr= %#016jx size= %d\n", 21262d1d418eSSumit Saxena __func__, __LINE__, (uintmax_t)drvr_info_phys, drvr_info_len); 21272d1d418eSSumit Saxena 21282d1d418eSSumit Saxena if (!drvr_info) 21292d1d418eSSumit Saxena { 21302d1d418eSSumit Saxena retval = -1; 21312d1d418eSSumit Saxena printf(IOCNAME "Memory alloc for Driver Info failed\n", 21322d1d418eSSumit Saxena sc->name); 21332d1d418eSSumit Saxena goto out; 21342d1d418eSSumit Saxena } 21352d1d418eSSumit Saxena drvr_info->InformationLength = (drvr_info_len); 21362d1d418eSSumit Saxena strcpy(drvr_info->DriverSignature, "Broadcom"); 21372d1d418eSSumit Saxena strcpy(drvr_info->OsName, "FreeBSD"); 21382d1d418eSSumit Saxena strcpy(drvr_info->OsVersion, fmt_os_ver); 21392d1d418eSSumit Saxena strcpy(drvr_info->DriverName, MPI3MR_DRIVER_NAME); 21402d1d418eSSumit Saxena strcpy(drvr_info->DriverVersion, MPI3MR_DRIVER_VERSION); 21412d1d418eSSumit Saxena strcpy(drvr_info->DriverReleaseDate, MPI3MR_DRIVER_RELDATE); 21422d1d418eSSumit Saxena drvr_info->DriverCapabilities = 0; 21432d1d418eSSumit Saxena memcpy((U8 *)&sc->driver_info, (U8 *)drvr_info, sizeof(sc->driver_info)); 21442d1d418eSSumit Saxena 21452d1d418eSSumit Saxena memset(&iocinit_req, 0, sizeof(iocinit_req)); 21462d1d418eSSumit Saxena mtx_lock(&sc->init_cmds.completion.lock); 21472d1d418eSSumit Saxena if (sc->init_cmds.state & MPI3MR_CMD_PENDING) { 21482d1d418eSSumit Saxena retval = -1; 21492d1d418eSSumit Saxena printf(IOCNAME "Issue IOCInit: Init command is in use\n", 21502d1d418eSSumit Saxena sc->name); 21512d1d418eSSumit Saxena mtx_unlock(&sc->init_cmds.completion.lock); 21522d1d418eSSumit Saxena goto out; 21532d1d418eSSumit Saxena } 21542d1d418eSSumit Saxena sc->init_cmds.state = MPI3MR_CMD_PENDING; 21552d1d418eSSumit Saxena sc->init_cmds.is_waiting = 1; 21562d1d418eSSumit Saxena sc->init_cmds.callback = NULL; 21572d1d418eSSumit Saxena iocinit_req.HostTag = MPI3MR_HOSTTAG_INITCMDS; 21582d1d418eSSumit Saxena iocinit_req.Function = MPI3_FUNCTION_IOC_INIT; 21592d1d418eSSumit Saxena iocinit_req.MPIVersion.Struct.Dev = MPI3_VERSION_DEV; 21602d1d418eSSumit Saxena iocinit_req.MPIVersion.Struct.Unit = MPI3_VERSION_UNIT; 21612d1d418eSSumit Saxena iocinit_req.MPIVersion.Struct.Major = MPI3_VERSION_MAJOR; 21622d1d418eSSumit Saxena iocinit_req.MPIVersion.Struct.Minor = MPI3_VERSION_MINOR; 21632d1d418eSSumit Saxena iocinit_req.WhoInit = MPI3_WHOINIT_HOST_DRIVER; 21642d1d418eSSumit Saxena iocinit_req.ReplyFreeQueueDepth = sc->reply_free_q_sz; 21652d1d418eSSumit Saxena iocinit_req.ReplyFreeQueueAddress = 21662d1d418eSSumit Saxena sc->reply_free_q_phys; 21672d1d418eSSumit Saxena iocinit_req.SenseBufferLength = MPI3MR_SENSEBUF_SZ; 21682d1d418eSSumit Saxena iocinit_req.SenseBufferFreeQueueDepth = 21692d1d418eSSumit Saxena sc->sense_buf_q_sz; 21702d1d418eSSumit Saxena iocinit_req.SenseBufferFreeQueueAddress = 21712d1d418eSSumit Saxena sc->sense_buf_q_phys; 21722d1d418eSSumit Saxena iocinit_req.DriverInformationAddress = drvr_info_phys; 21732d1d418eSSumit Saxena 21742d1d418eSSumit Saxena getmicrotime(&now); 21752d1d418eSSumit Saxena time_in_msec = (now.tv_sec * 1000 + now.tv_usec/1000); 21762d1d418eSSumit Saxena iocinit_req.TimeStamp = htole64(time_in_msec); 21772d1d418eSSumit Saxena 21782d1d418eSSumit Saxena init_completion(&sc->init_cmds.completion); 21792d1d418eSSumit Saxena retval = mpi3mr_submit_admin_cmd(sc, &iocinit_req, 21802d1d418eSSumit Saxena sizeof(iocinit_req)); 21812d1d418eSSumit Saxena 21822d1d418eSSumit Saxena if (retval) { 21832d1d418eSSumit Saxena printf(IOCNAME "Issue IOCInit: Admin Post failed\n", 21842d1d418eSSumit Saxena sc->name); 21852d1d418eSSumit Saxena goto out_unlock; 21862d1d418eSSumit Saxena } 21872d1d418eSSumit Saxena 21882d1d418eSSumit Saxena wait_for_completion_timeout(&sc->init_cmds.completion, 21892d1d418eSSumit Saxena (MPI3MR_INTADMCMD_TIMEOUT)); 21902d1d418eSSumit Saxena if (!(sc->init_cmds.state & MPI3MR_CMD_COMPLETE)) { 21912d1d418eSSumit Saxena printf(IOCNAME "Issue IOCInit: command timed out\n", 21922d1d418eSSumit Saxena sc->name); 21932d1d418eSSumit Saxena mpi3mr_check_rh_fault_ioc(sc, 21942d1d418eSSumit Saxena MPI3MR_RESET_FROM_IOCINIT_TIMEOUT); 21952d1d418eSSumit Saxena sc->unrecoverable = 1; 21962d1d418eSSumit Saxena retval = -1; 21972d1d418eSSumit Saxena goto out_unlock; 21982d1d418eSSumit Saxena } 21992d1d418eSSumit Saxena 22002d1d418eSSumit Saxena if ((sc->init_cmds.ioc_status & MPI3_IOCSTATUS_STATUS_MASK) 22012d1d418eSSumit Saxena != MPI3_IOCSTATUS_SUCCESS ) { 22022d1d418eSSumit Saxena printf(IOCNAME "Issue IOCInit: Failed IOCStatus(0x%04x) " 22032d1d418eSSumit Saxena " Loginfo(0x%08x) \n" , sc->name, 22042d1d418eSSumit Saxena (sc->init_cmds.ioc_status & MPI3_IOCSTATUS_STATUS_MASK), 22052d1d418eSSumit Saxena sc->init_cmds.ioc_loginfo); 22062d1d418eSSumit Saxena retval = -1; 22072d1d418eSSumit Saxena goto out_unlock; 22082d1d418eSSumit Saxena } 22092d1d418eSSumit Saxena 22102d1d418eSSumit Saxena out_unlock: 22112d1d418eSSumit Saxena sc->init_cmds.state = MPI3MR_CMD_NOTUSED; 22122d1d418eSSumit Saxena mtx_unlock(&sc->init_cmds.completion.lock); 22132d1d418eSSumit Saxena 22142d1d418eSSumit Saxena out: 22152d1d418eSSumit Saxena if (drvr_info_phys != 0) 22162d1d418eSSumit Saxena bus_dmamap_unload(drvr_info_tag, drvr_info_map); 22172d1d418eSSumit Saxena if (drvr_info != NULL) 22182d1d418eSSumit Saxena bus_dmamem_free(drvr_info_tag, drvr_info, drvr_info_map); 22192d1d418eSSumit Saxena if (drvr_info_tag != NULL) 22202d1d418eSSumit Saxena bus_dma_tag_destroy(drvr_info_tag); 22212d1d418eSSumit Saxena return retval; 22222d1d418eSSumit Saxena } 22232d1d418eSSumit Saxena 22242d1d418eSSumit Saxena static void 22252d1d418eSSumit Saxena mpi3mr_display_ioc_info(struct mpi3mr_softc *sc) 22262d1d418eSSumit Saxena { 22272d1d418eSSumit Saxena int i = 0; 22282d1d418eSSumit Saxena char personality[16]; 22292d1d418eSSumit Saxena 22302d1d418eSSumit Saxena switch (sc->facts.personality) { 22312d1d418eSSumit Saxena case MPI3_IOCFACTS_FLAGS_PERSONALITY_EHBA: 22322d1d418eSSumit Saxena strcpy(personality, "Enhanced HBA"); 22332d1d418eSSumit Saxena break; 22342d1d418eSSumit Saxena case MPI3_IOCFACTS_FLAGS_PERSONALITY_RAID_DDR: 22352d1d418eSSumit Saxena strcpy(personality, "RAID"); 22362d1d418eSSumit Saxena break; 22372d1d418eSSumit Saxena default: 22382d1d418eSSumit Saxena strcpy(personality, "Unknown"); 22392d1d418eSSumit Saxena break; 22402d1d418eSSumit Saxena } 22412d1d418eSSumit Saxena 22422d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_INFO, "Current Personality: %s\n", personality); 22432d1d418eSSumit Saxena 224428a27434SWarner Losh mpi3mr_dprint(sc, MPI3MR_INFO, "%s\n", sc->fw_version); 22452d1d418eSSumit Saxena 22462d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_INFO, "Protocol=("); 22472d1d418eSSumit Saxena 22482d1d418eSSumit Saxena if (sc->facts.protocol_flags & 22492d1d418eSSumit Saxena MPI3_IOCFACTS_PROTOCOL_SCSI_INITIATOR) { 22502d1d418eSSumit Saxena printf("Initiator"); 22512d1d418eSSumit Saxena i++; 22522d1d418eSSumit Saxena } 22532d1d418eSSumit Saxena 22542d1d418eSSumit Saxena if (sc->facts.protocol_flags & 22552d1d418eSSumit Saxena MPI3_IOCFACTS_PROTOCOL_SCSI_TARGET) { 22562d1d418eSSumit Saxena printf("%sTarget", i ? "," : ""); 22572d1d418eSSumit Saxena i++; 22582d1d418eSSumit Saxena } 22592d1d418eSSumit Saxena 22602d1d418eSSumit Saxena if (sc->facts.protocol_flags & 22612d1d418eSSumit Saxena MPI3_IOCFACTS_PROTOCOL_NVME) { 22622d1d418eSSumit Saxena printf("%sNVMe attachment", i ? "," : ""); 22632d1d418eSSumit Saxena i++; 22642d1d418eSSumit Saxena } 22652d1d418eSSumit Saxena i = 0; 22662d1d418eSSumit Saxena printf("), "); 22672d1d418eSSumit Saxena printf("Capabilities=("); 22682d1d418eSSumit Saxena 22692d1d418eSSumit Saxena if (sc->facts.ioc_capabilities & 22702d1d418eSSumit Saxena MPI3_IOCFACTS_CAPABILITY_RAID_CAPABLE) { 22712d1d418eSSumit Saxena printf("RAID"); 22722d1d418eSSumit Saxena i++; 22732d1d418eSSumit Saxena } 22742d1d418eSSumit Saxena 22752d1d418eSSumit Saxena printf(")\n"); 22762d1d418eSSumit Saxena } 22772d1d418eSSumit Saxena 22782d1d418eSSumit Saxena /** 22792d1d418eSSumit Saxena * mpi3mr_unmask_events - Unmask events in event mask bitmap 22802d1d418eSSumit Saxena * @sc: Adapter instance reference 22812d1d418eSSumit Saxena * @event: MPI event ID 22822d1d418eSSumit Saxena * 22832d1d418eSSumit Saxena * Un mask the specific event by resetting the event_mask 22842d1d418eSSumit Saxena * bitmap. 22852d1d418eSSumit Saxena * 22862d1d418eSSumit Saxena * Return: None. 22872d1d418eSSumit Saxena */ 22882d1d418eSSumit Saxena static void mpi3mr_unmask_events(struct mpi3mr_softc *sc, U16 event) 22892d1d418eSSumit Saxena { 22902d1d418eSSumit Saxena U32 desired_event; 22912d1d418eSSumit Saxena 22922d1d418eSSumit Saxena if (event >= 128) 22932d1d418eSSumit Saxena return; 22942d1d418eSSumit Saxena 22952d1d418eSSumit Saxena desired_event = (1 << (event % 32)); 22962d1d418eSSumit Saxena 22972d1d418eSSumit Saxena if (event < 32) 22982d1d418eSSumit Saxena sc->event_masks[0] &= ~desired_event; 22992d1d418eSSumit Saxena else if (event < 64) 23002d1d418eSSumit Saxena sc->event_masks[1] &= ~desired_event; 23012d1d418eSSumit Saxena else if (event < 96) 23022d1d418eSSumit Saxena sc->event_masks[2] &= ~desired_event; 23032d1d418eSSumit Saxena else if (event < 128) 23042d1d418eSSumit Saxena sc->event_masks[3] &= ~desired_event; 23052d1d418eSSumit Saxena } 23062d1d418eSSumit Saxena 23072d1d418eSSumit Saxena static void mpi3mr_set_events_mask(struct mpi3mr_softc *sc) 23082d1d418eSSumit Saxena { 23092d1d418eSSumit Saxena int i; 23102d1d418eSSumit Saxena for (i = 0; i < MPI3_EVENT_NOTIFY_EVENTMASK_WORDS; i++) 23112d1d418eSSumit Saxena sc->event_masks[i] = -1; 23122d1d418eSSumit Saxena 23132d1d418eSSumit Saxena mpi3mr_unmask_events(sc, MPI3_EVENT_DEVICE_ADDED); 23142d1d418eSSumit Saxena mpi3mr_unmask_events(sc, MPI3_EVENT_DEVICE_INFO_CHANGED); 23152d1d418eSSumit Saxena mpi3mr_unmask_events(sc, MPI3_EVENT_DEVICE_STATUS_CHANGE); 23162d1d418eSSumit Saxena 23172d1d418eSSumit Saxena mpi3mr_unmask_events(sc, MPI3_EVENT_ENCL_DEVICE_STATUS_CHANGE); 23182d1d418eSSumit Saxena 23192d1d418eSSumit Saxena mpi3mr_unmask_events(sc, MPI3_EVENT_SAS_TOPOLOGY_CHANGE_LIST); 23202d1d418eSSumit Saxena mpi3mr_unmask_events(sc, MPI3_EVENT_SAS_DISCOVERY); 23212d1d418eSSumit Saxena mpi3mr_unmask_events(sc, MPI3_EVENT_SAS_DEVICE_DISCOVERY_ERROR); 23222d1d418eSSumit Saxena mpi3mr_unmask_events(sc, MPI3_EVENT_SAS_BROADCAST_PRIMITIVE); 23232d1d418eSSumit Saxena 23242d1d418eSSumit Saxena mpi3mr_unmask_events(sc, MPI3_EVENT_PCIE_TOPOLOGY_CHANGE_LIST); 23252d1d418eSSumit Saxena mpi3mr_unmask_events(sc, MPI3_EVENT_PCIE_ENUMERATION); 23262d1d418eSSumit Saxena 23272d1d418eSSumit Saxena mpi3mr_unmask_events(sc, MPI3_EVENT_PREPARE_FOR_RESET); 23282d1d418eSSumit Saxena mpi3mr_unmask_events(sc, MPI3_EVENT_CABLE_MGMT); 23292d1d418eSSumit Saxena mpi3mr_unmask_events(sc, MPI3_EVENT_ENERGY_PACK_CHANGE); 23302d1d418eSSumit Saxena } 23312d1d418eSSumit Saxena 23322d1d418eSSumit Saxena /** 23332d1d418eSSumit Saxena * mpi3mr_issue_event_notification - Send event notification 23342d1d418eSSumit Saxena * @sc: Adapter instance reference 23352d1d418eSSumit Saxena * 23362d1d418eSSumit Saxena * Issue event notification MPI request through admin queue and 23372d1d418eSSumit Saxena * wait for the completion of it or time out. 23382d1d418eSSumit Saxena * 23392d1d418eSSumit Saxena * Return: 0 on success, non-zero on failures. 23402d1d418eSSumit Saxena */ 23412d1d418eSSumit Saxena int mpi3mr_issue_event_notification(struct mpi3mr_softc *sc) 23422d1d418eSSumit Saxena { 23432d1d418eSSumit Saxena Mpi3EventNotificationRequest_t evtnotify_req; 23442d1d418eSSumit Saxena int retval = 0; 23452d1d418eSSumit Saxena U8 i; 23462d1d418eSSumit Saxena 23472d1d418eSSumit Saxena memset(&evtnotify_req, 0, sizeof(evtnotify_req)); 23482d1d418eSSumit Saxena mtx_lock(&sc->init_cmds.completion.lock); 23492d1d418eSSumit Saxena if (sc->init_cmds.state & MPI3MR_CMD_PENDING) { 23502d1d418eSSumit Saxena retval = -1; 23512d1d418eSSumit Saxena printf(IOCNAME "Issue EvtNotify: Init command is in use\n", 23522d1d418eSSumit Saxena sc->name); 23532d1d418eSSumit Saxena mtx_unlock(&sc->init_cmds.completion.lock); 23542d1d418eSSumit Saxena goto out; 23552d1d418eSSumit Saxena } 23562d1d418eSSumit Saxena sc->init_cmds.state = MPI3MR_CMD_PENDING; 23572d1d418eSSumit Saxena sc->init_cmds.is_waiting = 1; 23582d1d418eSSumit Saxena sc->init_cmds.callback = NULL; 23592d1d418eSSumit Saxena evtnotify_req.HostTag = (MPI3MR_HOSTTAG_INITCMDS); 23602d1d418eSSumit Saxena evtnotify_req.Function = MPI3_FUNCTION_EVENT_NOTIFICATION; 23612d1d418eSSumit Saxena for (i = 0; i < MPI3_EVENT_NOTIFY_EVENTMASK_WORDS; i++) 23622d1d418eSSumit Saxena evtnotify_req.EventMasks[i] = 23632d1d418eSSumit Saxena (sc->event_masks[i]); 23642d1d418eSSumit Saxena init_completion(&sc->init_cmds.completion); 23652d1d418eSSumit Saxena retval = mpi3mr_submit_admin_cmd(sc, &evtnotify_req, 23662d1d418eSSumit Saxena sizeof(evtnotify_req)); 23672d1d418eSSumit Saxena if (retval) { 23682d1d418eSSumit Saxena printf(IOCNAME "Issue EvtNotify: Admin Post failed\n", 23692d1d418eSSumit Saxena sc->name); 23702d1d418eSSumit Saxena goto out_unlock; 23712d1d418eSSumit Saxena } 23722d1d418eSSumit Saxena 23732d1d418eSSumit Saxena poll_for_command_completion(sc, 23742d1d418eSSumit Saxena &sc->init_cmds, 23752d1d418eSSumit Saxena (MPI3MR_INTADMCMD_TIMEOUT)); 23762d1d418eSSumit Saxena if (!(sc->init_cmds.state & MPI3MR_CMD_COMPLETE)) { 23772d1d418eSSumit Saxena printf(IOCNAME "Issue EvtNotify: command timed out\n", 23782d1d418eSSumit Saxena sc->name); 23792d1d418eSSumit Saxena mpi3mr_check_rh_fault_ioc(sc, 23802d1d418eSSumit Saxena MPI3MR_RESET_FROM_EVTNOTIFY_TIMEOUT); 23812d1d418eSSumit Saxena retval = -1; 23822d1d418eSSumit Saxena goto out_unlock; 23832d1d418eSSumit Saxena } 23842d1d418eSSumit Saxena 23852d1d418eSSumit Saxena if ((sc->init_cmds.ioc_status & MPI3_IOCSTATUS_STATUS_MASK) 23862d1d418eSSumit Saxena != MPI3_IOCSTATUS_SUCCESS ) { 23872d1d418eSSumit Saxena printf(IOCNAME "Issue EvtNotify: Failed IOCStatus(0x%04x) " 23882d1d418eSSumit Saxena " Loginfo(0x%08x) \n" , sc->name, 23892d1d418eSSumit Saxena (sc->init_cmds.ioc_status & MPI3_IOCSTATUS_STATUS_MASK), 23902d1d418eSSumit Saxena sc->init_cmds.ioc_loginfo); 23912d1d418eSSumit Saxena retval = -1; 23922d1d418eSSumit Saxena goto out_unlock; 23932d1d418eSSumit Saxena } 23942d1d418eSSumit Saxena 23952d1d418eSSumit Saxena out_unlock: 23962d1d418eSSumit Saxena sc->init_cmds.state = MPI3MR_CMD_NOTUSED; 23972d1d418eSSumit Saxena mtx_unlock(&sc->init_cmds.completion.lock); 23982d1d418eSSumit Saxena 23992d1d418eSSumit Saxena out: 24002d1d418eSSumit Saxena return retval; 24012d1d418eSSumit Saxena } 24022d1d418eSSumit Saxena 24032d1d418eSSumit Saxena int 24042d1d418eSSumit Saxena mpi3mr_register_events(struct mpi3mr_softc *sc) 24052d1d418eSSumit Saxena { 24062d1d418eSSumit Saxena int error; 24072d1d418eSSumit Saxena 24082d1d418eSSumit Saxena mpi3mr_set_events_mask(sc); 24092d1d418eSSumit Saxena 24102d1d418eSSumit Saxena error = mpi3mr_issue_event_notification(sc); 24112d1d418eSSumit Saxena 24122d1d418eSSumit Saxena if (error) { 24132d1d418eSSumit Saxena printf(IOCNAME "Failed to issue event notification %d\n", 24142d1d418eSSumit Saxena sc->name, error); 24152d1d418eSSumit Saxena } 24162d1d418eSSumit Saxena 24172d1d418eSSumit Saxena return error; 24182d1d418eSSumit Saxena } 24192d1d418eSSumit Saxena 24202d1d418eSSumit Saxena /** 24212d1d418eSSumit Saxena * mpi3mr_process_event_ack - Process event acknowledgment 24222d1d418eSSumit Saxena * @sc: Adapter instance reference 24232d1d418eSSumit Saxena * @event: MPI3 event ID 24242d1d418eSSumit Saxena * @event_ctx: Event context 24252d1d418eSSumit Saxena * 24262d1d418eSSumit Saxena * Send event acknowledgement through admin queue and wait for 24272d1d418eSSumit Saxena * it to complete. 24282d1d418eSSumit Saxena * 24292d1d418eSSumit Saxena * Return: 0 on success, non-zero on failures. 24302d1d418eSSumit Saxena */ 24312d1d418eSSumit Saxena int mpi3mr_process_event_ack(struct mpi3mr_softc *sc, U8 event, 24322d1d418eSSumit Saxena U32 event_ctx) 24332d1d418eSSumit Saxena { 24342d1d418eSSumit Saxena Mpi3EventAckRequest_t evtack_req; 24352d1d418eSSumit Saxena int retval = 0; 24362d1d418eSSumit Saxena 24372d1d418eSSumit Saxena memset(&evtack_req, 0, sizeof(evtack_req)); 24382d1d418eSSumit Saxena mtx_lock(&sc->init_cmds.completion.lock); 24392d1d418eSSumit Saxena if (sc->init_cmds.state & MPI3MR_CMD_PENDING) { 24402d1d418eSSumit Saxena retval = -1; 24412d1d418eSSumit Saxena printf(IOCNAME "Issue EvtAck: Init command is in use\n", 24422d1d418eSSumit Saxena sc->name); 24432d1d418eSSumit Saxena mtx_unlock(&sc->init_cmds.completion.lock); 24442d1d418eSSumit Saxena goto out; 24452d1d418eSSumit Saxena } 24462d1d418eSSumit Saxena sc->init_cmds.state = MPI3MR_CMD_PENDING; 24472d1d418eSSumit Saxena sc->init_cmds.is_waiting = 1; 24482d1d418eSSumit Saxena sc->init_cmds.callback = NULL; 24492d1d418eSSumit Saxena evtack_req.HostTag = htole16(MPI3MR_HOSTTAG_INITCMDS); 24502d1d418eSSumit Saxena evtack_req.Function = MPI3_FUNCTION_EVENT_ACK; 24512d1d418eSSumit Saxena evtack_req.Event = event; 24522d1d418eSSumit Saxena evtack_req.EventContext = htole32(event_ctx); 24532d1d418eSSumit Saxena 24542d1d418eSSumit Saxena init_completion(&sc->init_cmds.completion); 24552d1d418eSSumit Saxena retval = mpi3mr_submit_admin_cmd(sc, &evtack_req, 24562d1d418eSSumit Saxena sizeof(evtack_req)); 24572d1d418eSSumit Saxena if (retval) { 24582d1d418eSSumit Saxena printf(IOCNAME "Issue EvtAck: Admin Post failed\n", 24592d1d418eSSumit Saxena sc->name); 24602d1d418eSSumit Saxena goto out_unlock; 24612d1d418eSSumit Saxena } 24622d1d418eSSumit Saxena 24632d1d418eSSumit Saxena wait_for_completion_timeout(&sc->init_cmds.completion, 24642d1d418eSSumit Saxena (MPI3MR_INTADMCMD_TIMEOUT)); 24652d1d418eSSumit Saxena if (!(sc->init_cmds.state & MPI3MR_CMD_COMPLETE)) { 24662d1d418eSSumit Saxena printf(IOCNAME "Issue EvtAck: command timed out\n", 24672d1d418eSSumit Saxena sc->name); 24682d1d418eSSumit Saxena retval = -1; 24692d1d418eSSumit Saxena goto out_unlock; 24702d1d418eSSumit Saxena } 24712d1d418eSSumit Saxena 24722d1d418eSSumit Saxena if ((sc->init_cmds.ioc_status & MPI3_IOCSTATUS_STATUS_MASK) 24732d1d418eSSumit Saxena != MPI3_IOCSTATUS_SUCCESS ) { 24742d1d418eSSumit Saxena printf(IOCNAME "Issue EvtAck: Failed IOCStatus(0x%04x) " 24752d1d418eSSumit Saxena " Loginfo(0x%08x) \n" , sc->name, 24762d1d418eSSumit Saxena (sc->init_cmds.ioc_status & MPI3_IOCSTATUS_STATUS_MASK), 24772d1d418eSSumit Saxena sc->init_cmds.ioc_loginfo); 24782d1d418eSSumit Saxena retval = -1; 24792d1d418eSSumit Saxena goto out_unlock; 24802d1d418eSSumit Saxena } 24812d1d418eSSumit Saxena 24822d1d418eSSumit Saxena out_unlock: 24832d1d418eSSumit Saxena sc->init_cmds.state = MPI3MR_CMD_NOTUSED; 24842d1d418eSSumit Saxena mtx_unlock(&sc->init_cmds.completion.lock); 24852d1d418eSSumit Saxena 24862d1d418eSSumit Saxena out: 24872d1d418eSSumit Saxena return retval; 24882d1d418eSSumit Saxena } 24892d1d418eSSumit Saxena 24902d1d418eSSumit Saxena 24912d1d418eSSumit Saxena static int mpi3mr_alloc_chain_bufs(struct mpi3mr_softc *sc) 24922d1d418eSSumit Saxena { 24932d1d418eSSumit Saxena int retval = 0; 24942d1d418eSSumit Saxena U32 sz, i; 24952d1d418eSSumit Saxena U16 num_chains; 24962d1d418eSSumit Saxena 24972d1d418eSSumit Saxena num_chains = sc->max_host_ios; 24982d1d418eSSumit Saxena 24992d1d418eSSumit Saxena sc->chain_buf_count = num_chains; 25002d1d418eSSumit Saxena sz = sizeof(struct mpi3mr_chain) * num_chains; 25012d1d418eSSumit Saxena 25022d1d418eSSumit Saxena sc->chain_sgl_list = malloc(sz, M_MPI3MR, M_NOWAIT | M_ZERO); 25032d1d418eSSumit Saxena 25042d1d418eSSumit Saxena if (!sc->chain_sgl_list) { 25052d1d418eSSumit Saxena printf(IOCNAME "Cannot allocate memory for chain SGL list\n", 25062d1d418eSSumit Saxena sc->name); 25072d1d418eSSumit Saxena retval = -1; 25082d1d418eSSumit Saxena goto out_failed; 25092d1d418eSSumit Saxena } 25102d1d418eSSumit Saxena 25112d1d418eSSumit Saxena sz = MPI3MR_CHAINSGE_SIZE; 25122d1d418eSSumit Saxena 25132d1d418eSSumit Saxena if (bus_dma_tag_create(sc->mpi3mr_parent_dmat, /* parent */ 25142d1d418eSSumit Saxena 4096, 0, /* algnmnt, boundary */ 2515ee7c431cSWarner Losh sc->dma_loaddr, /* lowaddr */ 25161ec7c672SWarner Losh BUS_SPACE_MAXADDR, /* highaddr */ 25172d1d418eSSumit Saxena NULL, NULL, /* filter, filterarg */ 25182d1d418eSSumit Saxena sz, /* maxsize */ 25192d1d418eSSumit Saxena 1, /* nsegments */ 25202d1d418eSSumit Saxena sz, /* maxsegsize */ 25212d1d418eSSumit Saxena 0, /* flags */ 25222d1d418eSSumit Saxena NULL, NULL, /* lockfunc, lockarg */ 25232d1d418eSSumit Saxena &sc->chain_sgl_list_tag)) { 25242d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_ERROR, "Cannot allocate Chain buffer DMA tag\n"); 25252d1d418eSSumit Saxena return (ENOMEM); 25262d1d418eSSumit Saxena } 25272d1d418eSSumit Saxena 25282d1d418eSSumit Saxena for (i = 0; i < num_chains; i++) { 25292d1d418eSSumit Saxena if (bus_dmamem_alloc(sc->chain_sgl_list_tag, (void **)&sc->chain_sgl_list[i].buf, 25302d1d418eSSumit Saxena BUS_DMA_NOWAIT, &sc->chain_sgl_list[i].buf_dmamap)) { 25312d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_ERROR, "Func: %s line: %d DMA mem alloc failed\n", 25322d1d418eSSumit Saxena __func__, __LINE__); 25332d1d418eSSumit Saxena return (ENOMEM); 25342d1d418eSSumit Saxena } 25352d1d418eSSumit Saxena 25362d1d418eSSumit Saxena bzero(sc->chain_sgl_list[i].buf, sz); 25372d1d418eSSumit Saxena bus_dmamap_load(sc->chain_sgl_list_tag, sc->chain_sgl_list[i].buf_dmamap, sc->chain_sgl_list[i].buf, sz, 253839a3e6a8SAlexander Motin mpi3mr_memaddr_cb, &sc->chain_sgl_list[i].buf_phys, BUS_DMA_NOWAIT); 25392d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_XINFO, "Func: %s line: %d phys addr= %#016jx size= %d\n", 25402d1d418eSSumit Saxena __func__, __LINE__, (uintmax_t)sc->chain_sgl_list[i].buf_phys, sz); 25412d1d418eSSumit Saxena } 25422d1d418eSSumit Saxena 25432d1d418eSSumit Saxena sc->chain_bitmap_sz = MPI3MR_DIV_ROUND_UP(num_chains, 8); 25442d1d418eSSumit Saxena 25452d1d418eSSumit Saxena sc->chain_bitmap = malloc(sc->chain_bitmap_sz, M_MPI3MR, M_NOWAIT | M_ZERO); 25462d1d418eSSumit Saxena if (!sc->chain_bitmap) { 25472d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_INFO, "Cannot alloc memory for chain bitmap\n"); 25482d1d418eSSumit Saxena retval = -1; 25492d1d418eSSumit Saxena goto out_failed; 25502d1d418eSSumit Saxena } 25512d1d418eSSumit Saxena return retval; 25522d1d418eSSumit Saxena 25532d1d418eSSumit Saxena out_failed: 25542d1d418eSSumit Saxena for (i = 0; i < num_chains; i++) { 25552d1d418eSSumit Saxena if (sc->chain_sgl_list[i].buf_phys != 0) 25562d1d418eSSumit Saxena bus_dmamap_unload(sc->chain_sgl_list_tag, sc->chain_sgl_list[i].buf_dmamap); 25572d1d418eSSumit Saxena if (sc->chain_sgl_list[i].buf != NULL) 25582d1d418eSSumit Saxena bus_dmamem_free(sc->chain_sgl_list_tag, sc->chain_sgl_list[i].buf, sc->chain_sgl_list[i].buf_dmamap); 25592d1d418eSSumit Saxena } 25602d1d418eSSumit Saxena if (sc->chain_sgl_list_tag != NULL) 25612d1d418eSSumit Saxena bus_dma_tag_destroy(sc->chain_sgl_list_tag); 25622d1d418eSSumit Saxena return retval; 25632d1d418eSSumit Saxena } 25642d1d418eSSumit Saxena 25652d1d418eSSumit Saxena static int mpi3mr_pel_alloc(struct mpi3mr_softc *sc) 25662d1d418eSSumit Saxena { 25672d1d418eSSumit Saxena int retval = 0; 25682d1d418eSSumit Saxena 25692d1d418eSSumit Saxena if (!sc->pel_cmds.reply) { 25702d1d418eSSumit Saxena sc->pel_cmds.reply = malloc(sc->reply_sz, M_MPI3MR, M_NOWAIT | M_ZERO); 25712d1d418eSSumit Saxena if (!sc->pel_cmds.reply) { 25722d1d418eSSumit Saxena printf(IOCNAME "Cannot allocate memory for pel_cmds.reply\n", 25732d1d418eSSumit Saxena sc->name); 25742d1d418eSSumit Saxena goto out_failed; 25752d1d418eSSumit Saxena } 25762d1d418eSSumit Saxena } 25772d1d418eSSumit Saxena 25782d1d418eSSumit Saxena if (!sc->pel_abort_cmd.reply) { 25792d1d418eSSumit Saxena sc->pel_abort_cmd.reply = malloc(sc->reply_sz, M_MPI3MR, M_NOWAIT | M_ZERO); 25802d1d418eSSumit Saxena if (!sc->pel_abort_cmd.reply) { 25812d1d418eSSumit Saxena printf(IOCNAME "Cannot allocate memory for pel_abort_cmd.reply\n", 25822d1d418eSSumit Saxena sc->name); 25832d1d418eSSumit Saxena goto out_failed; 25842d1d418eSSumit Saxena } 25852d1d418eSSumit Saxena } 25862d1d418eSSumit Saxena 25872d1d418eSSumit Saxena if (!sc->pel_seq_number) { 25882d1d418eSSumit Saxena sc->pel_seq_number_sz = sizeof(Mpi3PELSeq_t); 25892d1d418eSSumit Saxena if (bus_dma_tag_create(sc->mpi3mr_parent_dmat, /* parent */ 25902d1d418eSSumit Saxena 4, 0, /* alignment, boundary */ 2591ee7c431cSWarner Losh sc->dma_loaddr, /* lowaddr */ 25921ec7c672SWarner Losh BUS_SPACE_MAXADDR, /* highaddr */ 25932d1d418eSSumit Saxena NULL, NULL, /* filter, filterarg */ 25942d1d418eSSumit Saxena sc->pel_seq_number_sz, /* maxsize */ 25952d1d418eSSumit Saxena 1, /* nsegments */ 25962d1d418eSSumit Saxena sc->pel_seq_number_sz, /* maxsegsize */ 25972d1d418eSSumit Saxena 0, /* flags */ 25982d1d418eSSumit Saxena NULL, NULL, /* lockfunc, lockarg */ 25992d1d418eSSumit Saxena &sc->pel_seq_num_dmatag)) { 26002d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_ERROR, "Cannot create PEL seq number dma memory tag\n"); 26012d1d418eSSumit Saxena retval = -ENOMEM; 26022d1d418eSSumit Saxena goto out_failed; 26032d1d418eSSumit Saxena } 26042d1d418eSSumit Saxena 26052d1d418eSSumit Saxena if (bus_dmamem_alloc(sc->pel_seq_num_dmatag, (void **)&sc->pel_seq_number, 26062d1d418eSSumit Saxena BUS_DMA_NOWAIT, &sc->pel_seq_num_dmamap)) { 26072d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_ERROR, "Cannot allocate PEL seq number kernel buffer dma memory\n"); 26082d1d418eSSumit Saxena retval = -ENOMEM; 26092d1d418eSSumit Saxena goto out_failed; 26102d1d418eSSumit Saxena } 26112d1d418eSSumit Saxena 26122d1d418eSSumit Saxena bzero(sc->pel_seq_number, sc->pel_seq_number_sz); 26132d1d418eSSumit Saxena 26142d1d418eSSumit Saxena bus_dmamap_load(sc->pel_seq_num_dmatag, sc->pel_seq_num_dmamap, sc->pel_seq_number, 261539a3e6a8SAlexander Motin sc->pel_seq_number_sz, mpi3mr_memaddr_cb, &sc->pel_seq_number_dma, BUS_DMA_NOWAIT); 26162d1d418eSSumit Saxena 26172d1d418eSSumit Saxena if (!sc->pel_seq_number) { 26182d1d418eSSumit Saxena printf(IOCNAME "%s:%d Cannot load PEL seq number dma memory for size: %d\n", sc->name, 26192d1d418eSSumit Saxena __func__, __LINE__, sc->pel_seq_number_sz); 26202d1d418eSSumit Saxena retval = -ENOMEM; 26212d1d418eSSumit Saxena goto out_failed; 26222d1d418eSSumit Saxena } 26232d1d418eSSumit Saxena } 26242d1d418eSSumit Saxena 26252d1d418eSSumit Saxena out_failed: 26262d1d418eSSumit Saxena return retval; 26272d1d418eSSumit Saxena } 26282d1d418eSSumit Saxena 26292d1d418eSSumit Saxena /** 26302d1d418eSSumit Saxena * mpi3mr_validate_fw_update - validate IOCFacts post adapter reset 26312d1d418eSSumit Saxena * @sc: Adapter instance reference 26322d1d418eSSumit Saxena * 26332d1d418eSSumit Saxena * Return zero if the new IOCFacts is compatible with previous values 26342d1d418eSSumit Saxena * else return appropriate error 26352d1d418eSSumit Saxena */ 26362d1d418eSSumit Saxena static int 26372d1d418eSSumit Saxena mpi3mr_validate_fw_update(struct mpi3mr_softc *sc) 26382d1d418eSSumit Saxena { 26392d1d418eSSumit Saxena U16 dev_handle_bitmap_sz; 26402d1d418eSSumit Saxena U8 *removepend_bitmap; 26412d1d418eSSumit Saxena 26422d1d418eSSumit Saxena if (sc->facts.reply_sz > sc->reply_sz) { 26432d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_ERROR, 26442d1d418eSSumit Saxena "Cannot increase reply size from %d to %d\n", 26452d1d418eSSumit Saxena sc->reply_sz, sc->reply_sz); 26462d1d418eSSumit Saxena return -EPERM; 26472d1d418eSSumit Saxena } 26482d1d418eSSumit Saxena 26492d1d418eSSumit Saxena if (sc->num_io_throttle_group != sc->facts.max_io_throttle_group) { 26502d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_ERROR, 26512d1d418eSSumit Saxena "max io throttle group doesn't match old(%d), new(%d)\n", 26522d1d418eSSumit Saxena sc->num_io_throttle_group, 26532d1d418eSSumit Saxena sc->facts.max_io_throttle_group); 26542d1d418eSSumit Saxena return -EPERM; 26552d1d418eSSumit Saxena } 26562d1d418eSSumit Saxena 26572d1d418eSSumit Saxena if (sc->facts.max_op_reply_q < sc->num_queues) { 26582d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_ERROR, 26592d1d418eSSumit Saxena "Cannot reduce number of operational reply queues from %d to %d\n", 26602d1d418eSSumit Saxena sc->num_queues, 26612d1d418eSSumit Saxena sc->facts.max_op_reply_q); 26622d1d418eSSumit Saxena return -EPERM; 26632d1d418eSSumit Saxena } 26642d1d418eSSumit Saxena 26652d1d418eSSumit Saxena if (sc->facts.max_op_req_q < sc->num_queues) { 26662d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_ERROR, 26672d1d418eSSumit Saxena "Cannot reduce number of operational request queues from %d to %d\n", 26682d1d418eSSumit Saxena sc->num_queues, sc->facts.max_op_req_q); 26692d1d418eSSumit Saxena return -EPERM; 26702d1d418eSSumit Saxena } 26712d1d418eSSumit Saxena 26722d1d418eSSumit Saxena dev_handle_bitmap_sz = MPI3MR_DIV_ROUND_UP(sc->facts.max_devhandle, 8); 26732d1d418eSSumit Saxena 26742d1d418eSSumit Saxena if (dev_handle_bitmap_sz > sc->dev_handle_bitmap_sz) { 26752d1d418eSSumit Saxena removepend_bitmap = realloc(sc->removepend_bitmap, 26762d1d418eSSumit Saxena dev_handle_bitmap_sz, M_MPI3MR, M_NOWAIT); 26772d1d418eSSumit Saxena 26782d1d418eSSumit Saxena if (!removepend_bitmap) { 26792d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_ERROR, 26802d1d418eSSumit Saxena "failed to increase removepend_bitmap sz from: %d to %d\n", 26812d1d418eSSumit Saxena sc->dev_handle_bitmap_sz, dev_handle_bitmap_sz); 26822d1d418eSSumit Saxena return -ENOMEM; 26832d1d418eSSumit Saxena } 26842d1d418eSSumit Saxena 26852d1d418eSSumit Saxena memset(removepend_bitmap + sc->dev_handle_bitmap_sz, 0, 26862d1d418eSSumit Saxena dev_handle_bitmap_sz - sc->dev_handle_bitmap_sz); 26872d1d418eSSumit Saxena sc->removepend_bitmap = removepend_bitmap; 26882d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_INFO, 26892d1d418eSSumit Saxena "increased dev_handle_bitmap_sz from %d to %d\n", 26902d1d418eSSumit Saxena sc->dev_handle_bitmap_sz, dev_handle_bitmap_sz); 26912d1d418eSSumit Saxena sc->dev_handle_bitmap_sz = dev_handle_bitmap_sz; 26922d1d418eSSumit Saxena } 26932d1d418eSSumit Saxena 26942d1d418eSSumit Saxena return 0; 26952d1d418eSSumit Saxena } 26962d1d418eSSumit Saxena 26972d1d418eSSumit Saxena /* 26982d1d418eSSumit Saxena * mpi3mr_initialize_ioc - Controller initialization 26992d1d418eSSumit Saxena * @dev: pointer to device struct 27002d1d418eSSumit Saxena * 27012d1d418eSSumit Saxena * This function allocates the controller wide resources and brings 27022d1d418eSSumit Saxena * the controller to operational state 27032d1d418eSSumit Saxena * 27042d1d418eSSumit Saxena * Return: 0 on success and proper error codes on failure 27052d1d418eSSumit Saxena */ 27062d1d418eSSumit Saxena int mpi3mr_initialize_ioc(struct mpi3mr_softc *sc, U8 init_type) 27072d1d418eSSumit Saxena { 27082d1d418eSSumit Saxena int retval = 0; 27092d1d418eSSumit Saxena enum mpi3mr_iocstate ioc_state; 27102d1d418eSSumit Saxena U64 ioc_info; 27112d1d418eSSumit Saxena U32 ioc_status, ioc_control, i, timeout; 27122d1d418eSSumit Saxena Mpi3IOCFactsData_t facts_data; 27132d1d418eSSumit Saxena char str[32]; 27142d1d418eSSumit Saxena U32 size; 27152d1d418eSSumit Saxena 27162d1d418eSSumit Saxena sc->cpu_count = mp_ncpus; 27172d1d418eSSumit Saxena 27182d1d418eSSumit Saxena ioc_status = mpi3mr_regread(sc, MPI3_SYSIF_IOC_STATUS_OFFSET); 27192d1d418eSSumit Saxena ioc_control = mpi3mr_regread(sc, MPI3_SYSIF_IOC_CONFIG_OFFSET); 27202d1d418eSSumit Saxena ioc_info = mpi3mr_regread64(sc, MPI3_SYSIF_IOC_INFO_LOW_OFFSET); 27212d1d418eSSumit Saxena 27222d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_INFO, "SOD ioc_status: 0x%x ioc_control: 0x%x " 27232d1d418eSSumit Saxena "ioc_info: 0x%lx\n", ioc_status, ioc_control, ioc_info); 27242d1d418eSSumit Saxena 27252d1d418eSSumit Saxena /*The timeout value is in 2sec unit, changing it to seconds*/ 27262d1d418eSSumit Saxena sc->ready_timeout = 27272d1d418eSSumit Saxena ((ioc_info & MPI3_SYSIF_IOC_INFO_LOW_TIMEOUT_MASK) >> 27282d1d418eSSumit Saxena MPI3_SYSIF_IOC_INFO_LOW_TIMEOUT_SHIFT) * 2; 27292d1d418eSSumit Saxena 27302d1d418eSSumit Saxena ioc_state = mpi3mr_get_iocstate(sc); 27312d1d418eSSumit Saxena 27322d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_INFO, "IOC state: %s IOC ready timeout: %d\n", 27332d1d418eSSumit Saxena mpi3mr_iocstate_name(ioc_state), sc->ready_timeout); 27342d1d418eSSumit Saxena 27352d1d418eSSumit Saxena if (ioc_state == MRIOC_STATE_BECOMING_READY || 27362d1d418eSSumit Saxena ioc_state == MRIOC_STATE_RESET_REQUESTED) { 27372d1d418eSSumit Saxena timeout = sc->ready_timeout * 10; 27382d1d418eSSumit Saxena do { 27392d1d418eSSumit Saxena DELAY(1000 * 100); 27402d1d418eSSumit Saxena } while (--timeout); 27412d1d418eSSumit Saxena 27422d1d418eSSumit Saxena ioc_state = mpi3mr_get_iocstate(sc); 27432d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_INFO, 27442d1d418eSSumit Saxena "IOC in %s state after waiting for reset time\n", 27452d1d418eSSumit Saxena mpi3mr_iocstate_name(ioc_state)); 27462d1d418eSSumit Saxena } 27472d1d418eSSumit Saxena 27482d1d418eSSumit Saxena if (ioc_state == MRIOC_STATE_READY) { 27492d1d418eSSumit Saxena retval = mpi3mr_mur_ioc(sc, MPI3MR_RESET_FROM_BRINGUP); 27502d1d418eSSumit Saxena if (retval) { 27512d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_ERROR, "Failed to MU reset IOC, error 0x%x\n", 27522d1d418eSSumit Saxena retval); 27532d1d418eSSumit Saxena } 27542d1d418eSSumit Saxena ioc_state = mpi3mr_get_iocstate(sc); 27552d1d418eSSumit Saxena } 27562d1d418eSSumit Saxena 27572d1d418eSSumit Saxena if (ioc_state != MRIOC_STATE_RESET) { 27582d1d418eSSumit Saxena mpi3mr_print_fault_info(sc); 27592d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_ERROR, "issuing soft reset to bring to reset state\n"); 27602d1d418eSSumit Saxena retval = mpi3mr_issue_reset(sc, 27612d1d418eSSumit Saxena MPI3_SYSIF_HOST_DIAG_RESET_ACTION_SOFT_RESET, 27622d1d418eSSumit Saxena MPI3MR_RESET_FROM_BRINGUP); 27632d1d418eSSumit Saxena if (retval) { 27642d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_ERROR, 27652d1d418eSSumit Saxena "%s :Failed to soft reset IOC, error 0x%d\n", 27662d1d418eSSumit Saxena __func__, retval); 27672d1d418eSSumit Saxena goto out_failed; 27682d1d418eSSumit Saxena } 27692d1d418eSSumit Saxena } 27702d1d418eSSumit Saxena 27712d1d418eSSumit Saxena ioc_state = mpi3mr_get_iocstate(sc); 27722d1d418eSSumit Saxena 27732d1d418eSSumit Saxena if (ioc_state != MRIOC_STATE_RESET) { 27742d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_ERROR, "Cannot bring IOC to reset state\n"); 27752d1d418eSSumit Saxena goto out_failed; 27762d1d418eSSumit Saxena } 27772d1d418eSSumit Saxena 27782d1d418eSSumit Saxena retval = mpi3mr_setup_admin_qpair(sc); 27792d1d418eSSumit Saxena if (retval) { 27802d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_ERROR, "Failed to setup Admin queues, error 0x%x\n", 27812d1d418eSSumit Saxena retval); 27822d1d418eSSumit Saxena goto out_failed; 27832d1d418eSSumit Saxena } 27842d1d418eSSumit Saxena 27852d1d418eSSumit Saxena retval = mpi3mr_bring_ioc_ready(sc); 27862d1d418eSSumit Saxena if (retval) { 27872d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_ERROR, "Failed to bring IOC ready, error 0x%x\n", 27882d1d418eSSumit Saxena retval); 27892d1d418eSSumit Saxena goto out_failed; 27902d1d418eSSumit Saxena } 27912d1d418eSSumit Saxena 27922d1d418eSSumit Saxena if (init_type == MPI3MR_INIT_TYPE_INIT) { 27932d1d418eSSumit Saxena retval = mpi3mr_alloc_interrupts(sc, 1); 27942d1d418eSSumit Saxena if (retval) { 27952d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_ERROR, "Failed to allocate interrupts, error 0x%x\n", 27962d1d418eSSumit Saxena retval); 27972d1d418eSSumit Saxena goto out_failed; 27982d1d418eSSumit Saxena } 27992d1d418eSSumit Saxena 28002d1d418eSSumit Saxena retval = mpi3mr_setup_irqs(sc); 28012d1d418eSSumit Saxena if (retval) { 28022d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_ERROR, "Failed to setup ISR, error 0x%x\n", 28032d1d418eSSumit Saxena retval); 28042d1d418eSSumit Saxena goto out_failed; 28052d1d418eSSumit Saxena } 28062d1d418eSSumit Saxena } 28072d1d418eSSumit Saxena 28082d1d418eSSumit Saxena mpi3mr_enable_interrupts(sc); 28092d1d418eSSumit Saxena 28102d1d418eSSumit Saxena if (init_type == MPI3MR_INIT_TYPE_INIT) { 28112d1d418eSSumit Saxena mtx_init(&sc->mpi3mr_mtx, "SIM lock", NULL, MTX_DEF); 28122d1d418eSSumit Saxena mtx_init(&sc->io_lock, "IO lock", NULL, MTX_DEF); 28132d1d418eSSumit Saxena mtx_init(&sc->admin_req_lock, "Admin Request Queue lock", NULL, MTX_SPIN); 28142d1d418eSSumit Saxena mtx_init(&sc->reply_free_q_lock, "Reply free Queue lock", NULL, MTX_SPIN); 28152d1d418eSSumit Saxena mtx_init(&sc->sense_buf_q_lock, "Sense buffer Queue lock", NULL, MTX_SPIN); 28162d1d418eSSumit Saxena mtx_init(&sc->chain_buf_lock, "Chain buffer lock", NULL, MTX_SPIN); 28172d1d418eSSumit Saxena mtx_init(&sc->cmd_pool_lock, "Command pool lock", NULL, MTX_DEF); 28182d1d418eSSumit Saxena mtx_init(&sc->fwevt_lock, "Firmware Event lock", NULL, MTX_DEF); 28192d1d418eSSumit Saxena mtx_init(&sc->target_lock, "Target lock", NULL, MTX_SPIN); 28202d1d418eSSumit Saxena mtx_init(&sc->reset_mutex, "Reset lock", NULL, MTX_DEF); 28212d1d418eSSumit Saxena 28222d1d418eSSumit Saxena mtx_init(&sc->init_cmds.completion.lock, "Init commands lock", NULL, MTX_DEF); 28232d1d418eSSumit Saxena sc->init_cmds.reply = NULL; 28242d1d418eSSumit Saxena sc->init_cmds.state = MPI3MR_CMD_NOTUSED; 28252d1d418eSSumit Saxena sc->init_cmds.dev_handle = MPI3MR_INVALID_DEV_HANDLE; 28262d1d418eSSumit Saxena sc->init_cmds.host_tag = MPI3MR_HOSTTAG_INITCMDS; 28272d1d418eSSumit Saxena 28282d1d418eSSumit Saxena mtx_init(&sc->ioctl_cmds.completion.lock, "IOCTL commands lock", NULL, MTX_DEF); 28292d1d418eSSumit Saxena sc->ioctl_cmds.reply = NULL; 28302d1d418eSSumit Saxena sc->ioctl_cmds.state = MPI3MR_CMD_NOTUSED; 28312d1d418eSSumit Saxena sc->ioctl_cmds.dev_handle = MPI3MR_INVALID_DEV_HANDLE; 28322d1d418eSSumit Saxena sc->ioctl_cmds.host_tag = MPI3MR_HOSTTAG_IOCTLCMDS; 28332d1d418eSSumit Saxena 28342d1d418eSSumit Saxena mtx_init(&sc->pel_abort_cmd.completion.lock, "PEL Abort command lock", NULL, MTX_DEF); 28352d1d418eSSumit Saxena sc->pel_abort_cmd.reply = NULL; 28362d1d418eSSumit Saxena sc->pel_abort_cmd.state = MPI3MR_CMD_NOTUSED; 28372d1d418eSSumit Saxena sc->pel_abort_cmd.dev_handle = MPI3MR_INVALID_DEV_HANDLE; 28382d1d418eSSumit Saxena sc->pel_abort_cmd.host_tag = MPI3MR_HOSTTAG_PELABORT; 28392d1d418eSSumit Saxena 28402d1d418eSSumit Saxena mtx_init(&sc->host_tm_cmds.completion.lock, "TM commands lock", NULL, MTX_DEF); 28412d1d418eSSumit Saxena sc->host_tm_cmds.reply = NULL; 28422d1d418eSSumit Saxena sc->host_tm_cmds.state = MPI3MR_CMD_NOTUSED; 28432d1d418eSSumit Saxena sc->host_tm_cmds.dev_handle = MPI3MR_INVALID_DEV_HANDLE; 28442d1d418eSSumit Saxena sc->host_tm_cmds.host_tag = MPI3MR_HOSTTAG_TMS; 28452d1d418eSSumit Saxena 28462d1d418eSSumit Saxena TAILQ_INIT(&sc->cmd_list_head); 28472d1d418eSSumit Saxena TAILQ_INIT(&sc->event_list); 28482d1d418eSSumit Saxena TAILQ_INIT(&sc->delayed_rmhs_list); 28492d1d418eSSumit Saxena TAILQ_INIT(&sc->delayed_evtack_cmds_list); 28502d1d418eSSumit Saxena 28512d1d418eSSumit Saxena for (i = 0; i < MPI3MR_NUM_DEVRMCMD; i++) { 28522d1d418eSSumit Saxena snprintf(str, 32, "Dev REMHS commands lock[%d]", i); 28532d1d418eSSumit Saxena mtx_init(&sc->dev_rmhs_cmds[i].completion.lock, str, NULL, MTX_DEF); 28542d1d418eSSumit Saxena sc->dev_rmhs_cmds[i].reply = NULL; 28552d1d418eSSumit Saxena sc->dev_rmhs_cmds[i].state = MPI3MR_CMD_NOTUSED; 28562d1d418eSSumit Saxena sc->dev_rmhs_cmds[i].dev_handle = MPI3MR_INVALID_DEV_HANDLE; 28572d1d418eSSumit Saxena sc->dev_rmhs_cmds[i].host_tag = MPI3MR_HOSTTAG_DEVRMCMD_MIN 28582d1d418eSSumit Saxena + i; 28592d1d418eSSumit Saxena } 28602d1d418eSSumit Saxena } 28612d1d418eSSumit Saxena 28622d1d418eSSumit Saxena retval = mpi3mr_issue_iocfacts(sc, &facts_data); 28632d1d418eSSumit Saxena if (retval) { 28642d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_ERROR, "Failed to Issue IOC Facts, retval: 0x%x\n", 28652d1d418eSSumit Saxena retval); 28662d1d418eSSumit Saxena goto out_failed; 28672d1d418eSSumit Saxena } 28682d1d418eSSumit Saxena 28692d1d418eSSumit Saxena retval = mpi3mr_process_factsdata(sc, &facts_data); 28702d1d418eSSumit Saxena if (retval) { 28712d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_ERROR, "IOC Facts data processing failedi, retval: 0x%x\n", 28722d1d418eSSumit Saxena retval); 28732d1d418eSSumit Saxena goto out_failed; 28742d1d418eSSumit Saxena } 28752d1d418eSSumit Saxena 28762d1d418eSSumit Saxena sc->num_io_throttle_group = sc->facts.max_io_throttle_group; 28772d1d418eSSumit Saxena mpi3mr_atomic_set(&sc->pend_large_data_sz, 0); 28782d1d418eSSumit Saxena 28792d1d418eSSumit Saxena if (init_type == MPI3MR_INIT_TYPE_RESET) { 28802d1d418eSSumit Saxena retval = mpi3mr_validate_fw_update(sc); 28812d1d418eSSumit Saxena if (retval) 28822d1d418eSSumit Saxena goto out_failed; 28832d1d418eSSumit Saxena } else { 28842d1d418eSSumit Saxena sc->reply_sz = sc->facts.reply_sz; 28852d1d418eSSumit Saxena } 28862d1d418eSSumit Saxena 28872d1d418eSSumit Saxena mpi3mr_display_ioc_info(sc); 28882d1d418eSSumit Saxena 28892d1d418eSSumit Saxena retval = mpi3mr_reply_alloc(sc); 28902d1d418eSSumit Saxena if (retval) { 28912d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_ERROR, "Failed to allocated reply and sense buffers, retval: 0x%x\n", 28922d1d418eSSumit Saxena retval); 28932d1d418eSSumit Saxena goto out_failed; 28942d1d418eSSumit Saxena } 28952d1d418eSSumit Saxena 28962d1d418eSSumit Saxena if (init_type == MPI3MR_INIT_TYPE_INIT) { 28972d1d418eSSumit Saxena retval = mpi3mr_alloc_chain_bufs(sc); 28982d1d418eSSumit Saxena if (retval) { 28992d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_ERROR, "Failed to allocated chain buffers, retval: 0x%x\n", 29002d1d418eSSumit Saxena retval); 29012d1d418eSSumit Saxena goto out_failed; 29022d1d418eSSumit Saxena } 29032d1d418eSSumit Saxena } 29042d1d418eSSumit Saxena 29052d1d418eSSumit Saxena retval = mpi3mr_issue_iocinit(sc); 29062d1d418eSSumit Saxena if (retval) { 29072d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_ERROR, "Failed to Issue IOC Init, retval: 0x%x\n", 29082d1d418eSSumit Saxena retval); 29092d1d418eSSumit Saxena goto out_failed; 29102d1d418eSSumit Saxena } 29112d1d418eSSumit Saxena 29122d1d418eSSumit Saxena mpi3mr_print_fw_pkg_ver(sc); 29132d1d418eSSumit Saxena 29142d1d418eSSumit Saxena sc->reply_free_q_host_index = sc->num_reply_bufs; 29152d1d418eSSumit Saxena mpi3mr_regwrite(sc, MPI3_SYSIF_REPLY_FREE_HOST_INDEX_OFFSET, 29162d1d418eSSumit Saxena sc->reply_free_q_host_index); 29172d1d418eSSumit Saxena 29182d1d418eSSumit Saxena sc->sense_buf_q_host_index = sc->num_sense_bufs; 29192d1d418eSSumit Saxena 29202d1d418eSSumit Saxena mpi3mr_regwrite(sc, MPI3_SYSIF_SENSE_BUF_FREE_HOST_INDEX_OFFSET, 29212d1d418eSSumit Saxena sc->sense_buf_q_host_index); 29222d1d418eSSumit Saxena 29232d1d418eSSumit Saxena if (init_type == MPI3MR_INIT_TYPE_INIT) { 29242d1d418eSSumit Saxena retval = mpi3mr_alloc_interrupts(sc, 0); 29252d1d418eSSumit Saxena if (retval) { 29262d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_ERROR, "Failed to allocate interrupts, retval: 0x%x\n", 29272d1d418eSSumit Saxena retval); 29282d1d418eSSumit Saxena goto out_failed; 29292d1d418eSSumit Saxena } 29302d1d418eSSumit Saxena 29312d1d418eSSumit Saxena retval = mpi3mr_setup_irqs(sc); 29322d1d418eSSumit Saxena if (retval) { 29332d1d418eSSumit Saxena printf(IOCNAME "Failed to setup ISR, error: 0x%x\n", 29342d1d418eSSumit Saxena sc->name, retval); 29352d1d418eSSumit Saxena goto out_failed; 29362d1d418eSSumit Saxena } 29372d1d418eSSumit Saxena 29382d1d418eSSumit Saxena mpi3mr_enable_interrupts(sc); 29392d1d418eSSumit Saxena 29402d1d418eSSumit Saxena } else 29412d1d418eSSumit Saxena mpi3mr_enable_interrupts(sc); 29422d1d418eSSumit Saxena 29432d1d418eSSumit Saxena retval = mpi3mr_create_op_queues(sc); 29442d1d418eSSumit Saxena 29452d1d418eSSumit Saxena if (retval) { 29462d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_ERROR, "Failed to create operational queues, error: %d\n", 29472d1d418eSSumit Saxena retval); 29482d1d418eSSumit Saxena goto out_failed; 29492d1d418eSSumit Saxena } 29502d1d418eSSumit Saxena 29512d1d418eSSumit Saxena if (!sc->throttle_groups && sc->num_io_throttle_group) { 29522d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_ERROR, "allocating memory for throttle groups\n"); 29532d1d418eSSumit Saxena size = sizeof(struct mpi3mr_throttle_group_info); 29542d1d418eSSumit Saxena sc->throttle_groups = (struct mpi3mr_throttle_group_info *) 29552d1d418eSSumit Saxena malloc(sc->num_io_throttle_group * 29562d1d418eSSumit Saxena size, M_MPI3MR, M_NOWAIT | M_ZERO); 29572d1d418eSSumit Saxena if (!sc->throttle_groups) 29582d1d418eSSumit Saxena goto out_failed; 29592d1d418eSSumit Saxena } 29602d1d418eSSumit Saxena 29612d1d418eSSumit Saxena if (init_type == MPI3MR_INIT_TYPE_RESET) { 29622d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_INFO, "Re-register events\n"); 29632d1d418eSSumit Saxena retval = mpi3mr_register_events(sc); 29642d1d418eSSumit Saxena if (retval) { 29652d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_INFO, "Failed to re-register events, retval: 0x%x\n", 29662d1d418eSSumit Saxena retval); 29672d1d418eSSumit Saxena goto out_failed; 29682d1d418eSSumit Saxena } 29692d1d418eSSumit Saxena 29702d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_INFO, "Issuing Port Enable\n"); 29712d1d418eSSumit Saxena retval = mpi3mr_issue_port_enable(sc, 0); 29722d1d418eSSumit Saxena if (retval) { 29732d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_INFO, "Failed to issue port enable, retval: 0x%x\n", 29742d1d418eSSumit Saxena retval); 29752d1d418eSSumit Saxena goto out_failed; 29762d1d418eSSumit Saxena } 29772d1d418eSSumit Saxena } 29782d1d418eSSumit Saxena retval = mpi3mr_pel_alloc(sc); 29792d1d418eSSumit Saxena if (retval) { 29802d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_ERROR, "Failed to allocate memory for PEL, retval: 0x%x\n", 29812d1d418eSSumit Saxena retval); 29822d1d418eSSumit Saxena goto out_failed; 29832d1d418eSSumit Saxena } 29842d1d418eSSumit Saxena 29852d1d418eSSumit Saxena return retval; 29862d1d418eSSumit Saxena 29872d1d418eSSumit Saxena out_failed: 29882d1d418eSSumit Saxena retval = -1; 29892d1d418eSSumit Saxena return retval; 29902d1d418eSSumit Saxena } 29912d1d418eSSumit Saxena 29922d1d418eSSumit Saxena static void mpi3mr_port_enable_complete(struct mpi3mr_softc *sc, 29932d1d418eSSumit Saxena struct mpi3mr_drvr_cmd *drvrcmd) 29942d1d418eSSumit Saxena { 29952d1d418eSSumit Saxena drvrcmd->state = MPI3MR_CMD_NOTUSED; 29962d1d418eSSumit Saxena drvrcmd->callback = NULL; 29972d1d418eSSumit Saxena printf(IOCNAME "Completing Port Enable Request\n", sc->name); 29982d1d418eSSumit Saxena sc->mpi3mr_flags |= MPI3MR_FLAGS_PORT_ENABLE_DONE; 29992d1d418eSSumit Saxena mpi3mr_startup_decrement(sc->cam_sc); 30002d1d418eSSumit Saxena } 30012d1d418eSSumit Saxena 30022d1d418eSSumit Saxena int mpi3mr_issue_port_enable(struct mpi3mr_softc *sc, U8 async) 30032d1d418eSSumit Saxena { 30042d1d418eSSumit Saxena Mpi3PortEnableRequest_t pe_req; 30052d1d418eSSumit Saxena int retval = 0; 30062d1d418eSSumit Saxena 30072d1d418eSSumit Saxena memset(&pe_req, 0, sizeof(pe_req)); 30082d1d418eSSumit Saxena mtx_lock(&sc->init_cmds.completion.lock); 30092d1d418eSSumit Saxena if (sc->init_cmds.state & MPI3MR_CMD_PENDING) { 30102d1d418eSSumit Saxena retval = -1; 30112d1d418eSSumit Saxena printf(IOCNAME "Issue PortEnable: Init command is in use\n", sc->name); 30122d1d418eSSumit Saxena mtx_unlock(&sc->init_cmds.completion.lock); 30132d1d418eSSumit Saxena goto out; 30142d1d418eSSumit Saxena } 30152d1d418eSSumit Saxena 30162d1d418eSSumit Saxena sc->init_cmds.state = MPI3MR_CMD_PENDING; 30172d1d418eSSumit Saxena 30182d1d418eSSumit Saxena if (async) { 30192d1d418eSSumit Saxena sc->init_cmds.is_waiting = 0; 30202d1d418eSSumit Saxena sc->init_cmds.callback = mpi3mr_port_enable_complete; 30212d1d418eSSumit Saxena } else { 30222d1d418eSSumit Saxena sc->init_cmds.is_waiting = 1; 30232d1d418eSSumit Saxena sc->init_cmds.callback = NULL; 30242d1d418eSSumit Saxena init_completion(&sc->init_cmds.completion); 30252d1d418eSSumit Saxena } 30262d1d418eSSumit Saxena pe_req.HostTag = MPI3MR_HOSTTAG_INITCMDS; 30272d1d418eSSumit Saxena pe_req.Function = MPI3_FUNCTION_PORT_ENABLE; 30282d1d418eSSumit Saxena 30292d1d418eSSumit Saxena printf(IOCNAME "Sending Port Enable Request\n", sc->name); 30302d1d418eSSumit Saxena retval = mpi3mr_submit_admin_cmd(sc, &pe_req, sizeof(pe_req)); 30312d1d418eSSumit Saxena if (retval) { 30322d1d418eSSumit Saxena printf(IOCNAME "Issue PortEnable: Admin Post failed\n", 30332d1d418eSSumit Saxena sc->name); 30342d1d418eSSumit Saxena goto out_unlock; 30352d1d418eSSumit Saxena } 30362d1d418eSSumit Saxena 30372d1d418eSSumit Saxena if (!async) { 30382d1d418eSSumit Saxena wait_for_completion_timeout(&sc->init_cmds.completion, 30392d1d418eSSumit Saxena MPI3MR_PORTENABLE_TIMEOUT); 30402d1d418eSSumit Saxena if (!(sc->init_cmds.state & MPI3MR_CMD_COMPLETE)) { 30412d1d418eSSumit Saxena printf(IOCNAME "Issue PortEnable: command timed out\n", 30422d1d418eSSumit Saxena sc->name); 30432d1d418eSSumit Saxena retval = -1; 30442d1d418eSSumit Saxena mpi3mr_check_rh_fault_ioc(sc, MPI3MR_RESET_FROM_PE_TIMEOUT); 30452d1d418eSSumit Saxena goto out_unlock; 30462d1d418eSSumit Saxena } 30472d1d418eSSumit Saxena mpi3mr_port_enable_complete(sc, &sc->init_cmds); 30482d1d418eSSumit Saxena } 30492d1d418eSSumit Saxena out_unlock: 30502d1d418eSSumit Saxena mtx_unlock(&sc->init_cmds.completion.lock); 30512d1d418eSSumit Saxena 30522d1d418eSSumit Saxena out: 30532d1d418eSSumit Saxena return retval; 30542d1d418eSSumit Saxena } 30552d1d418eSSumit Saxena 30562d1d418eSSumit Saxena void 30572d1d418eSSumit Saxena mpi3mr_watchdog_thread(void *arg) 30582d1d418eSSumit Saxena { 30592d1d418eSSumit Saxena struct mpi3mr_softc *sc; 30602d1d418eSSumit Saxena enum mpi3mr_iocstate ioc_state; 30612d1d418eSSumit Saxena U32 fault, host_diagnostic, ioc_status; 30622d1d418eSSumit Saxena 30632d1d418eSSumit Saxena sc = (struct mpi3mr_softc *)arg; 30642d1d418eSSumit Saxena 30652d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_XINFO, "%s\n", __func__); 30662d1d418eSSumit Saxena 30672d1d418eSSumit Saxena sc->watchdog_thread_active = 1; 30682d1d418eSSumit Saxena mtx_lock(&sc->reset_mutex); 30692d1d418eSSumit Saxena for (;;) { 30702d1d418eSSumit Saxena if (sc->mpi3mr_flags & MPI3MR_FLAGS_SHUTDOWN || 30712d1d418eSSumit Saxena (sc->unrecoverable == 1)) { 30722d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_INFO, 30732d1d418eSSumit Saxena "Exit due to %s from %s\n", 30742d1d418eSSumit Saxena sc->mpi3mr_flags & MPI3MR_FLAGS_SHUTDOWN ? "Shutdown" : 30752d1d418eSSumit Saxena "Hardware critical error", __func__); 30762d1d418eSSumit Saxena break; 30772d1d418eSSumit Saxena } 30787c491309SWarner Losh mtx_unlock(&sc->reset_mutex); 30792d1d418eSSumit Saxena 30802d1d418eSSumit Saxena if ((sc->prepare_for_reset) && 30812d1d418eSSumit Saxena ((sc->prepare_for_reset_timeout_counter++) >= 30822d1d418eSSumit Saxena MPI3MR_PREPARE_FOR_RESET_TIMEOUT)) { 30832d1d418eSSumit Saxena mpi3mr_soft_reset_handler(sc, 30842d1d418eSSumit Saxena MPI3MR_RESET_FROM_CIACTVRST_TIMER, 1); 30857c491309SWarner Losh goto sleep; 30862d1d418eSSumit Saxena } 30872d1d418eSSumit Saxena 30882d1d418eSSumit Saxena ioc_status = mpi3mr_regread(sc, MPI3_SYSIF_IOC_STATUS_OFFSET); 30892d1d418eSSumit Saxena 30902d1d418eSSumit Saxena if (ioc_status & MPI3_SYSIF_IOC_STATUS_RESET_HISTORY) { 30912d1d418eSSumit Saxena mpi3mr_soft_reset_handler(sc, MPI3MR_RESET_FROM_FIRMWARE, 0); 30927c491309SWarner Losh goto sleep; 30932d1d418eSSumit Saxena } 30942d1d418eSSumit Saxena 30952d1d418eSSumit Saxena ioc_state = mpi3mr_get_iocstate(sc); 30962d1d418eSSumit Saxena if (ioc_state == MRIOC_STATE_FAULT) { 30972d1d418eSSumit Saxena fault = mpi3mr_regread(sc, MPI3_SYSIF_FAULT_OFFSET) & 30982d1d418eSSumit Saxena MPI3_SYSIF_FAULT_CODE_MASK; 30992d1d418eSSumit Saxena 31002d1d418eSSumit Saxena host_diagnostic = mpi3mr_regread(sc, MPI3_SYSIF_HOST_DIAG_OFFSET); 31012d1d418eSSumit Saxena if (host_diagnostic & MPI3_SYSIF_HOST_DIAG_SAVE_IN_PROGRESS) { 31022d1d418eSSumit Saxena if (!sc->diagsave_timeout) { 31032d1d418eSSumit Saxena mpi3mr_print_fault_info(sc); 31042d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_INFO, 31052d1d418eSSumit Saxena "diag save in progress\n"); 31062d1d418eSSumit Saxena } 31072d1d418eSSumit Saxena if ((sc->diagsave_timeout++) <= MPI3_SYSIF_DIAG_SAVE_TIMEOUT) 31087c491309SWarner Losh goto sleep; 31092d1d418eSSumit Saxena } 31102d1d418eSSumit Saxena mpi3mr_print_fault_info(sc); 31112d1d418eSSumit Saxena sc->diagsave_timeout = 0; 31122d1d418eSSumit Saxena 31132d1d418eSSumit Saxena if ((fault == MPI3_SYSIF_FAULT_CODE_POWER_CYCLE_REQUIRED) || 31142d1d418eSSumit Saxena (fault == MPI3_SYSIF_FAULT_CODE_COMPLETE_RESET_NEEDED)) { 31152d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_INFO, 31162d1d418eSSumit Saxena "Controller requires system power cycle or complete reset is needed," 31172d1d418eSSumit Saxena "fault code: 0x%x. marking controller as unrecoverable\n", fault); 31182d1d418eSSumit Saxena sc->unrecoverable = 1; 31197c491309SWarner Losh break; 31202d1d418eSSumit Saxena } 31212d1d418eSSumit Saxena if ((fault == MPI3_SYSIF_FAULT_CODE_DIAG_FAULT_RESET) 31222d1d418eSSumit Saxena || (fault == MPI3_SYSIF_FAULT_CODE_SOFT_RESET_IN_PROGRESS) 31232d1d418eSSumit Saxena || (sc->reset_in_progress)) 31247c491309SWarner Losh break; 31252d1d418eSSumit Saxena if (fault == MPI3_SYSIF_FAULT_CODE_CI_ACTIVATION_RESET) 31262d1d418eSSumit Saxena mpi3mr_soft_reset_handler(sc, 31272d1d418eSSumit Saxena MPI3MR_RESET_FROM_CIACTIV_FAULT, 0); 31282d1d418eSSumit Saxena else 31292d1d418eSSumit Saxena mpi3mr_soft_reset_handler(sc, 31302d1d418eSSumit Saxena MPI3MR_RESET_FROM_FAULT_WATCH, 0); 31312d1d418eSSumit Saxena 31322d1d418eSSumit Saxena } 31332d1d418eSSumit Saxena 31342d1d418eSSumit Saxena if (sc->reset.type == MPI3MR_TRIGGER_SOFT_RESET) { 31352d1d418eSSumit Saxena mpi3mr_print_fault_info(sc); 31362d1d418eSSumit Saxena mpi3mr_soft_reset_handler(sc, sc->reset.reason, 1); 31372d1d418eSSumit Saxena } 31387c491309SWarner Losh sleep: 31397c491309SWarner Losh mtx_lock(&sc->reset_mutex); 31407c491309SWarner Losh /* 31417c491309SWarner Losh * Sleep for 1 second if we're not exiting, then loop to top 31427c491309SWarner Losh * to poll exit status and hardware health. 31437c491309SWarner Losh */ 31447c491309SWarner Losh if ((sc->mpi3mr_flags & MPI3MR_FLAGS_SHUTDOWN) == 0 && 31457c491309SWarner Losh !sc->unrecoverable) { 31467c491309SWarner Losh msleep(&sc->watchdog_chan, &sc->reset_mutex, PRIBIO, 31477c491309SWarner Losh "mpi3mr_watchdog", 1 * hz); 31482d1d418eSSumit Saxena } 31497c491309SWarner Losh } 31502d1d418eSSumit Saxena mtx_unlock(&sc->reset_mutex); 31512d1d418eSSumit Saxena sc->watchdog_thread_active = 0; 31522d1d418eSSumit Saxena mpi3mr_kproc_exit(0); 31532d1d418eSSumit Saxena } 31542d1d418eSSumit Saxena 31552d1d418eSSumit Saxena static void mpi3mr_display_event_data(struct mpi3mr_softc *sc, 31562d1d418eSSumit Saxena Mpi3EventNotificationReply_t *event_rep) 31572d1d418eSSumit Saxena { 31582d1d418eSSumit Saxena char *desc = NULL; 31592d1d418eSSumit Saxena U16 event; 31602d1d418eSSumit Saxena 31612d1d418eSSumit Saxena event = event_rep->Event; 31622d1d418eSSumit Saxena 31632d1d418eSSumit Saxena switch (event) { 31642d1d418eSSumit Saxena case MPI3_EVENT_LOG_DATA: 31652d1d418eSSumit Saxena desc = "Log Data"; 31662d1d418eSSumit Saxena break; 31672d1d418eSSumit Saxena case MPI3_EVENT_CHANGE: 31682d1d418eSSumit Saxena desc = "Event Change"; 31692d1d418eSSumit Saxena break; 31702d1d418eSSumit Saxena case MPI3_EVENT_GPIO_INTERRUPT: 31712d1d418eSSumit Saxena desc = "GPIO Interrupt"; 31722d1d418eSSumit Saxena break; 31732d1d418eSSumit Saxena case MPI3_EVENT_CABLE_MGMT: 31742d1d418eSSumit Saxena desc = "Cable Management"; 31752d1d418eSSumit Saxena break; 31762d1d418eSSumit Saxena case MPI3_EVENT_ENERGY_PACK_CHANGE: 31772d1d418eSSumit Saxena desc = "Energy Pack Change"; 31782d1d418eSSumit Saxena break; 31792d1d418eSSumit Saxena case MPI3_EVENT_DEVICE_ADDED: 31802d1d418eSSumit Saxena { 31812d1d418eSSumit Saxena Mpi3DevicePage0_t *event_data = 31822d1d418eSSumit Saxena (Mpi3DevicePage0_t *)event_rep->EventData; 31832d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_EVENT, "Device Added: Dev=0x%04x Form=0x%x Perst id: 0x%x\n", 31842d1d418eSSumit Saxena event_data->DevHandle, event_data->DeviceForm, event_data->PersistentID); 31852d1d418eSSumit Saxena return; 31862d1d418eSSumit Saxena } 31872d1d418eSSumit Saxena case MPI3_EVENT_DEVICE_INFO_CHANGED: 31882d1d418eSSumit Saxena { 31892d1d418eSSumit Saxena Mpi3DevicePage0_t *event_data = 31902d1d418eSSumit Saxena (Mpi3DevicePage0_t *)event_rep->EventData; 31912d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_EVENT, "Device Info Changed: Dev=0x%04x Form=0x%x\n", 31922d1d418eSSumit Saxena event_data->DevHandle, event_data->DeviceForm); 31932d1d418eSSumit Saxena return; 31942d1d418eSSumit Saxena } 31952d1d418eSSumit Saxena case MPI3_EVENT_DEVICE_STATUS_CHANGE: 31962d1d418eSSumit Saxena { 31972d1d418eSSumit Saxena Mpi3EventDataDeviceStatusChange_t *event_data = 31982d1d418eSSumit Saxena (Mpi3EventDataDeviceStatusChange_t *)event_rep->EventData; 31992d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_EVENT, "Device Status Change: Dev=0x%04x RC=0x%x\n", 32002d1d418eSSumit Saxena event_data->DevHandle, event_data->ReasonCode); 32012d1d418eSSumit Saxena return; 32022d1d418eSSumit Saxena } 32032d1d418eSSumit Saxena case MPI3_EVENT_SAS_DISCOVERY: 32042d1d418eSSumit Saxena { 32052d1d418eSSumit Saxena Mpi3EventDataSasDiscovery_t *event_data = 32062d1d418eSSumit Saxena (Mpi3EventDataSasDiscovery_t *)event_rep->EventData; 32072d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_EVENT, "SAS Discovery: (%s)", 32082d1d418eSSumit Saxena (event_data->ReasonCode == MPI3_EVENT_SAS_DISC_RC_STARTED) ? 32092d1d418eSSumit Saxena "start" : "stop"); 32102d1d418eSSumit Saxena if (event_data->DiscoveryStatus && 32112d1d418eSSumit Saxena (sc->mpi3mr_debug & MPI3MR_EVENT)) { 32122d1d418eSSumit Saxena printf("discovery_status(0x%08x)", 32132d1d418eSSumit Saxena event_data->DiscoveryStatus); 32142d1d418eSSumit Saxena 32152d1d418eSSumit Saxena } 32162d1d418eSSumit Saxena 32172d1d418eSSumit Saxena if (sc->mpi3mr_debug & MPI3MR_EVENT) 32182d1d418eSSumit Saxena printf("\n"); 32192d1d418eSSumit Saxena return; 32202d1d418eSSumit Saxena } 32212d1d418eSSumit Saxena case MPI3_EVENT_SAS_BROADCAST_PRIMITIVE: 32222d1d418eSSumit Saxena desc = "SAS Broadcast Primitive"; 32232d1d418eSSumit Saxena break; 32242d1d418eSSumit Saxena case MPI3_EVENT_SAS_NOTIFY_PRIMITIVE: 32252d1d418eSSumit Saxena desc = "SAS Notify Primitive"; 32262d1d418eSSumit Saxena break; 32272d1d418eSSumit Saxena case MPI3_EVENT_SAS_INIT_DEVICE_STATUS_CHANGE: 32282d1d418eSSumit Saxena desc = "SAS Init Device Status Change"; 32292d1d418eSSumit Saxena break; 32302d1d418eSSumit Saxena case MPI3_EVENT_SAS_INIT_TABLE_OVERFLOW: 32312d1d418eSSumit Saxena desc = "SAS Init Table Overflow"; 32322d1d418eSSumit Saxena break; 32332d1d418eSSumit Saxena case MPI3_EVENT_SAS_TOPOLOGY_CHANGE_LIST: 32342d1d418eSSumit Saxena desc = "SAS Topology Change List"; 32352d1d418eSSumit Saxena break; 32362d1d418eSSumit Saxena case MPI3_EVENT_ENCL_DEVICE_STATUS_CHANGE: 32372d1d418eSSumit Saxena desc = "Enclosure Device Status Change"; 32382d1d418eSSumit Saxena break; 32392d1d418eSSumit Saxena case MPI3_EVENT_HARD_RESET_RECEIVED: 32402d1d418eSSumit Saxena desc = "Hard Reset Received"; 32412d1d418eSSumit Saxena break; 32422d1d418eSSumit Saxena case MPI3_EVENT_SAS_PHY_COUNTER: 32432d1d418eSSumit Saxena desc = "SAS PHY Counter"; 32442d1d418eSSumit Saxena break; 32452d1d418eSSumit Saxena case MPI3_EVENT_SAS_DEVICE_DISCOVERY_ERROR: 32462d1d418eSSumit Saxena desc = "SAS Device Discovery Error"; 32472d1d418eSSumit Saxena break; 32482d1d418eSSumit Saxena case MPI3_EVENT_PCIE_TOPOLOGY_CHANGE_LIST: 32492d1d418eSSumit Saxena desc = "PCIE Topology Change List"; 32502d1d418eSSumit Saxena break; 32512d1d418eSSumit Saxena case MPI3_EVENT_PCIE_ENUMERATION: 32522d1d418eSSumit Saxena { 32532d1d418eSSumit Saxena Mpi3EventDataPcieEnumeration_t *event_data = 32542d1d418eSSumit Saxena (Mpi3EventDataPcieEnumeration_t *)event_rep->EventData; 32552d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_EVENT, "PCIE Enumeration: (%s)", 32562d1d418eSSumit Saxena (event_data->ReasonCode == 32572d1d418eSSumit Saxena MPI3_EVENT_PCIE_ENUM_RC_STARTED) ? "start" : 32582d1d418eSSumit Saxena "stop"); 32592d1d418eSSumit Saxena if (event_data->EnumerationStatus) 32602d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_EVENT, "enumeration_status(0x%08x)", 32612d1d418eSSumit Saxena event_data->EnumerationStatus); 32622d1d418eSSumit Saxena if (sc->mpi3mr_debug & MPI3MR_EVENT) 32632d1d418eSSumit Saxena printf("\n"); 32642d1d418eSSumit Saxena return; 32652d1d418eSSumit Saxena } 32662d1d418eSSumit Saxena case MPI3_EVENT_PREPARE_FOR_RESET: 32672d1d418eSSumit Saxena desc = "Prepare For Reset"; 32682d1d418eSSumit Saxena break; 32692d1d418eSSumit Saxena } 32702d1d418eSSumit Saxena 32712d1d418eSSumit Saxena if (!desc) 32722d1d418eSSumit Saxena return; 32732d1d418eSSumit Saxena 32742d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_EVENT, "%s\n", desc); 32752d1d418eSSumit Saxena } 32762d1d418eSSumit Saxena 32772d1d418eSSumit Saxena struct mpi3mr_target * 32782d1d418eSSumit Saxena mpi3mr_find_target_by_per_id(struct mpi3mr_cam_softc *cam_sc, 32792d1d418eSSumit Saxena uint16_t per_id) 32802d1d418eSSumit Saxena { 32812d1d418eSSumit Saxena struct mpi3mr_target *target = NULL; 32822d1d418eSSumit Saxena 32832d1d418eSSumit Saxena mtx_lock_spin(&cam_sc->sc->target_lock); 32842d1d418eSSumit Saxena TAILQ_FOREACH(target, &cam_sc->tgt_list, tgt_next) { 32852d1d418eSSumit Saxena if (target->per_id == per_id) 32862d1d418eSSumit Saxena break; 32872d1d418eSSumit Saxena } 32882d1d418eSSumit Saxena 32892d1d418eSSumit Saxena mtx_unlock_spin(&cam_sc->sc->target_lock); 32902d1d418eSSumit Saxena return target; 32912d1d418eSSumit Saxena } 32922d1d418eSSumit Saxena 32932d1d418eSSumit Saxena struct mpi3mr_target * 32942d1d418eSSumit Saxena mpi3mr_find_target_by_dev_handle(struct mpi3mr_cam_softc *cam_sc, 32952d1d418eSSumit Saxena uint16_t handle) 32962d1d418eSSumit Saxena { 32972d1d418eSSumit Saxena struct mpi3mr_target *target = NULL; 32982d1d418eSSumit Saxena 32992d1d418eSSumit Saxena mtx_lock_spin(&cam_sc->sc->target_lock); 33002d1d418eSSumit Saxena TAILQ_FOREACH(target, &cam_sc->tgt_list, tgt_next) { 33012d1d418eSSumit Saxena if (target->dev_handle == handle) 33022d1d418eSSumit Saxena break; 33032d1d418eSSumit Saxena 33042d1d418eSSumit Saxena } 33052d1d418eSSumit Saxena mtx_unlock_spin(&cam_sc->sc->target_lock); 33062d1d418eSSumit Saxena return target; 33072d1d418eSSumit Saxena } 33082d1d418eSSumit Saxena 33092d1d418eSSumit Saxena void mpi3mr_update_device(struct mpi3mr_softc *sc, 33102d1d418eSSumit Saxena struct mpi3mr_target *tgtdev, Mpi3DevicePage0_t *dev_pg0, 33112d1d418eSSumit Saxena bool is_added) 33122d1d418eSSumit Saxena { 33132d1d418eSSumit Saxena U16 flags = 0; 33142d1d418eSSumit Saxena 33152d1d418eSSumit Saxena tgtdev->per_id = (dev_pg0->PersistentID); 33162d1d418eSSumit Saxena tgtdev->dev_handle = (dev_pg0->DevHandle); 33172d1d418eSSumit Saxena tgtdev->dev_type = dev_pg0->DeviceForm; 33182d1d418eSSumit Saxena tgtdev->encl_handle = (dev_pg0->EnclosureHandle); 33192d1d418eSSumit Saxena tgtdev->parent_handle = (dev_pg0->ParentDevHandle); 33202d1d418eSSumit Saxena tgtdev->slot = (dev_pg0->Slot); 33212d1d418eSSumit Saxena tgtdev->qdepth = (dev_pg0->QueueDepth); 33222d1d418eSSumit Saxena tgtdev->wwid = (dev_pg0->WWID); 33232d1d418eSSumit Saxena 33242d1d418eSSumit Saxena flags = (dev_pg0->Flags); 33252d1d418eSSumit Saxena tgtdev->is_hidden = (flags & MPI3_DEVICE0_FLAGS_HIDDEN); 33262d1d418eSSumit Saxena if (is_added == true) 33272d1d418eSSumit Saxena tgtdev->io_throttle_enabled = 33282d1d418eSSumit Saxena (flags & MPI3_DEVICE0_FLAGS_IO_THROTTLING_REQUIRED) ? 1 : 0; 33292d1d418eSSumit Saxena 33302d1d418eSSumit Saxena switch (dev_pg0->AccessStatus) { 33312d1d418eSSumit Saxena case MPI3_DEVICE0_ASTATUS_NO_ERRORS: 33322d1d418eSSumit Saxena case MPI3_DEVICE0_ASTATUS_PREPARE: 33332d1d418eSSumit Saxena case MPI3_DEVICE0_ASTATUS_NEEDS_INITIALIZATION: 33342d1d418eSSumit Saxena case MPI3_DEVICE0_ASTATUS_DEVICE_MISSING_DELAY: 33352d1d418eSSumit Saxena break; 33362d1d418eSSumit Saxena default: 33372d1d418eSSumit Saxena tgtdev->is_hidden = 1; 33382d1d418eSSumit Saxena break; 33392d1d418eSSumit Saxena } 33402d1d418eSSumit Saxena 33412d1d418eSSumit Saxena switch (tgtdev->dev_type) { 33422d1d418eSSumit Saxena case MPI3_DEVICE_DEVFORM_SAS_SATA: 33432d1d418eSSumit Saxena { 33442d1d418eSSumit Saxena Mpi3Device0SasSataFormat_t *sasinf = 33452d1d418eSSumit Saxena &dev_pg0->DeviceSpecific.SasSataFormat; 33462d1d418eSSumit Saxena U16 dev_info = (sasinf->DeviceInfo); 33472d1d418eSSumit Saxena tgtdev->dev_spec.sassata_inf.dev_info = dev_info; 33482d1d418eSSumit Saxena tgtdev->dev_spec.sassata_inf.sas_address = 33492d1d418eSSumit Saxena (sasinf->SASAddress); 33502d1d418eSSumit Saxena if ((dev_info & MPI3_SAS_DEVICE_INFO_DEVICE_TYPE_MASK) != 33512d1d418eSSumit Saxena MPI3_SAS_DEVICE_INFO_DEVICE_TYPE_END_DEVICE) 33522d1d418eSSumit Saxena tgtdev->is_hidden = 1; 33532d1d418eSSumit Saxena else if (!(dev_info & (MPI3_SAS_DEVICE_INFO_STP_SATA_TARGET | 33542d1d418eSSumit Saxena MPI3_SAS_DEVICE_INFO_SSP_TARGET))) 33552d1d418eSSumit Saxena tgtdev->is_hidden = 1; 33562d1d418eSSumit Saxena break; 33572d1d418eSSumit Saxena } 33582d1d418eSSumit Saxena case MPI3_DEVICE_DEVFORM_PCIE: 33592d1d418eSSumit Saxena { 33602d1d418eSSumit Saxena Mpi3Device0PcieFormat_t *pcieinf = 33612d1d418eSSumit Saxena &dev_pg0->DeviceSpecific.PcieFormat; 33622d1d418eSSumit Saxena U16 dev_info = (pcieinf->DeviceInfo); 33632d1d418eSSumit Saxena 33642d1d418eSSumit Saxena tgtdev->q_depth = dev_pg0->QueueDepth; 33652d1d418eSSumit Saxena tgtdev->dev_spec.pcie_inf.dev_info = dev_info; 33662d1d418eSSumit Saxena tgtdev->dev_spec.pcie_inf.capb = 33672d1d418eSSumit Saxena (pcieinf->Capabilities); 33682d1d418eSSumit Saxena tgtdev->dev_spec.pcie_inf.mdts = MPI3MR_DEFAULT_MDTS; 33692d1d418eSSumit Saxena if (dev_pg0->AccessStatus == MPI3_DEVICE0_ASTATUS_NO_ERRORS) { 33702d1d418eSSumit Saxena tgtdev->dev_spec.pcie_inf.mdts = 33712d1d418eSSumit Saxena (pcieinf->MaximumDataTransferSize); 33722d1d418eSSumit Saxena tgtdev->dev_spec.pcie_inf.pgsz = pcieinf->PageSize; 33732d1d418eSSumit Saxena tgtdev->dev_spec.pcie_inf.reset_to = 33742d1d418eSSumit Saxena pcieinf->ControllerResetTO; 33752d1d418eSSumit Saxena tgtdev->dev_spec.pcie_inf.abort_to = 33762d1d418eSSumit Saxena pcieinf->NVMeAbortTO; 33772d1d418eSSumit Saxena } 33782d1d418eSSumit Saxena if (tgtdev->dev_spec.pcie_inf.mdts > (1024 * 1024)) 33792d1d418eSSumit Saxena tgtdev->dev_spec.pcie_inf.mdts = (1024 * 1024); 33802d1d418eSSumit Saxena 33812d1d418eSSumit Saxena if (((dev_info & MPI3_DEVICE0_PCIE_DEVICE_INFO_TYPE_MASK) != 33822d1d418eSSumit Saxena MPI3_DEVICE0_PCIE_DEVICE_INFO_TYPE_NVME_DEVICE) && 33832d1d418eSSumit Saxena ((dev_info & MPI3_DEVICE0_PCIE_DEVICE_INFO_TYPE_MASK) != 33842d1d418eSSumit Saxena MPI3_DEVICE0_PCIE_DEVICE_INFO_TYPE_SCSI_DEVICE)) 33852d1d418eSSumit Saxena tgtdev->is_hidden = 1; 33862d1d418eSSumit Saxena 33872d1d418eSSumit Saxena break; 33882d1d418eSSumit Saxena } 33892d1d418eSSumit Saxena case MPI3_DEVICE_DEVFORM_VD: 33902d1d418eSSumit Saxena { 33912d1d418eSSumit Saxena Mpi3Device0VdFormat_t *vdinf = 33922d1d418eSSumit Saxena &dev_pg0->DeviceSpecific.VdFormat; 33932d1d418eSSumit Saxena struct mpi3mr_throttle_group_info *tg = NULL; 33942d1d418eSSumit Saxena 33952d1d418eSSumit Saxena tgtdev->dev_spec.vol_inf.state = vdinf->VdState; 33962d1d418eSSumit Saxena if (vdinf->VdState == MPI3_DEVICE0_VD_STATE_OFFLINE) 33972d1d418eSSumit Saxena tgtdev->is_hidden = 1; 33982d1d418eSSumit Saxena tgtdev->dev_spec.vol_inf.tg_id = vdinf->IOThrottleGroup; 33992d1d418eSSumit Saxena tgtdev->dev_spec.vol_inf.tg_high = 34002d1d418eSSumit Saxena vdinf->IOThrottleGroupHigh * 2048; 34012d1d418eSSumit Saxena tgtdev->dev_spec.vol_inf.tg_low = 34022d1d418eSSumit Saxena vdinf->IOThrottleGroupLow * 2048; 34032d1d418eSSumit Saxena if (vdinf->IOThrottleGroup < sc->num_io_throttle_group) { 34042d1d418eSSumit Saxena tg = sc->throttle_groups + vdinf->IOThrottleGroup; 34052d1d418eSSumit Saxena tg->id = vdinf->IOThrottleGroup; 34062d1d418eSSumit Saxena tg->high = tgtdev->dev_spec.vol_inf.tg_high; 34072d1d418eSSumit Saxena tg->low = tgtdev->dev_spec.vol_inf.tg_low; 34082d1d418eSSumit Saxena if (is_added == true) 34092d1d418eSSumit Saxena tg->fw_qd = tgtdev->q_depth; 34102d1d418eSSumit Saxena tg->modified_qd = tgtdev->q_depth; 34112d1d418eSSumit Saxena } 34122d1d418eSSumit Saxena tgtdev->dev_spec.vol_inf.tg = tg; 34132d1d418eSSumit Saxena tgtdev->throttle_group = tg; 34142d1d418eSSumit Saxena break; 34152d1d418eSSumit Saxena } 34162d1d418eSSumit Saxena default: 34172d1d418eSSumit Saxena goto out; 34182d1d418eSSumit Saxena } 34192d1d418eSSumit Saxena 34202d1d418eSSumit Saxena out: 34212d1d418eSSumit Saxena return; 34222d1d418eSSumit Saxena } 34232d1d418eSSumit Saxena 34242d1d418eSSumit Saxena int mpi3mr_create_device(struct mpi3mr_softc *sc, 34252d1d418eSSumit Saxena Mpi3DevicePage0_t *dev_pg0) 34262d1d418eSSumit Saxena { 34272d1d418eSSumit Saxena int retval = 0; 34282d1d418eSSumit Saxena struct mpi3mr_target *target = NULL; 34292d1d418eSSumit Saxena U16 per_id = 0; 34302d1d418eSSumit Saxena 34312d1d418eSSumit Saxena per_id = dev_pg0->PersistentID; 34322d1d418eSSumit Saxena 34332d1d418eSSumit Saxena mtx_lock_spin(&sc->target_lock); 34342d1d418eSSumit Saxena TAILQ_FOREACH(target, &sc->cam_sc->tgt_list, tgt_next) { 34352d1d418eSSumit Saxena if (target->per_id == per_id) { 34362d1d418eSSumit Saxena target->state = MPI3MR_DEV_CREATED; 34372d1d418eSSumit Saxena break; 34382d1d418eSSumit Saxena } 34392d1d418eSSumit Saxena } 34402d1d418eSSumit Saxena mtx_unlock_spin(&sc->target_lock); 34412d1d418eSSumit Saxena 34422d1d418eSSumit Saxena if (target) { 34432d1d418eSSumit Saxena mpi3mr_update_device(sc, target, dev_pg0, true); 34442d1d418eSSumit Saxena } else { 34452d1d418eSSumit Saxena target = malloc(sizeof(*target), M_MPI3MR, 34462d1d418eSSumit Saxena M_NOWAIT | M_ZERO); 34472d1d418eSSumit Saxena 34482d1d418eSSumit Saxena if (target == NULL) { 34492d1d418eSSumit Saxena retval = -1; 34502d1d418eSSumit Saxena goto out; 34512d1d418eSSumit Saxena } 34522d1d418eSSumit Saxena 34532d1d418eSSumit Saxena target->exposed_to_os = 0; 34542d1d418eSSumit Saxena mpi3mr_update_device(sc, target, dev_pg0, true); 34552d1d418eSSumit Saxena mtx_lock_spin(&sc->target_lock); 34562d1d418eSSumit Saxena TAILQ_INSERT_TAIL(&sc->cam_sc->tgt_list, target, tgt_next); 34572d1d418eSSumit Saxena target->state = MPI3MR_DEV_CREATED; 34582d1d418eSSumit Saxena mtx_unlock_spin(&sc->target_lock); 34592d1d418eSSumit Saxena } 34602d1d418eSSumit Saxena out: 34612d1d418eSSumit Saxena return retval; 34622d1d418eSSumit Saxena } 34632d1d418eSSumit Saxena 34642d1d418eSSumit Saxena /** 34652d1d418eSSumit Saxena * mpi3mr_dev_rmhs_complete_iou - Device removal IOUC completion 34662d1d418eSSumit Saxena * @sc: Adapter instance reference 34672d1d418eSSumit Saxena * @drv_cmd: Internal command tracker 34682d1d418eSSumit Saxena * 34692d1d418eSSumit Saxena * Issues a target reset TM to the firmware from the device 34702d1d418eSSumit Saxena * removal TM pend list or retry the removal handshake sequence 34712d1d418eSSumit Saxena * based on the IOU control request IOC status. 34722d1d418eSSumit Saxena * 34732d1d418eSSumit Saxena * Return: Nothing 34742d1d418eSSumit Saxena */ 34752d1d418eSSumit Saxena static void mpi3mr_dev_rmhs_complete_iou(struct mpi3mr_softc *sc, 34762d1d418eSSumit Saxena struct mpi3mr_drvr_cmd *drv_cmd) 34772d1d418eSSumit Saxena { 34782d1d418eSSumit Saxena U16 cmd_idx = drv_cmd->host_tag - MPI3MR_HOSTTAG_DEVRMCMD_MIN; 34792d1d418eSSumit Saxena struct delayed_dev_rmhs_node *delayed_dev_rmhs = NULL; 3480701d776cSChandrakanth patil struct mpi3mr_target *tgtdev = NULL; 34812d1d418eSSumit Saxena 34822d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_EVENT, 34832d1d418eSSumit Saxena "%s :dev_rmhs_iouctrl_complete:handle(0x%04x), ioc_status(0x%04x), loginfo(0x%08x)\n", 34842d1d418eSSumit Saxena __func__, drv_cmd->dev_handle, drv_cmd->ioc_status, 34852d1d418eSSumit Saxena drv_cmd->ioc_loginfo); 34862d1d418eSSumit Saxena if (drv_cmd->ioc_status != MPI3_IOCSTATUS_SUCCESS) { 34872d1d418eSSumit Saxena if (drv_cmd->retry_count < MPI3MR_DEVRMHS_RETRYCOUNT) { 34882d1d418eSSumit Saxena drv_cmd->retry_count++; 34892d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_EVENT, 34902d1d418eSSumit Saxena "%s :dev_rmhs_iouctrl_complete: handle(0x%04x)retrying handshake retry=%d\n", 34912d1d418eSSumit Saxena __func__, drv_cmd->dev_handle, 34922d1d418eSSumit Saxena drv_cmd->retry_count); 34932d1d418eSSumit Saxena mpi3mr_dev_rmhs_send_tm(sc, drv_cmd->dev_handle, 34942d1d418eSSumit Saxena drv_cmd, drv_cmd->iou_rc); 34952d1d418eSSumit Saxena return; 34962d1d418eSSumit Saxena } 34972d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_ERROR, 34982d1d418eSSumit Saxena "%s :dev removal handshake failed after all retries: handle(0x%04x)\n", 34992d1d418eSSumit Saxena __func__, drv_cmd->dev_handle); 35002d1d418eSSumit Saxena } else { 3501701d776cSChandrakanth patil mtx_lock_spin(&sc->target_lock); 3502701d776cSChandrakanth patil TAILQ_FOREACH(tgtdev, &sc->cam_sc->tgt_list, tgt_next) { 3503701d776cSChandrakanth patil if (tgtdev->dev_handle == drv_cmd->dev_handle) 3504701d776cSChandrakanth patil tgtdev->state = MPI3MR_DEV_REMOVE_HS_COMPLETED; 3505701d776cSChandrakanth patil } 3506701d776cSChandrakanth patil mtx_unlock_spin(&sc->target_lock); 3507701d776cSChandrakanth patil 35082d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_INFO, 35092d1d418eSSumit Saxena "%s :dev removal handshake completed successfully: handle(0x%04x)\n", 35102d1d418eSSumit Saxena __func__, drv_cmd->dev_handle); 35112d1d418eSSumit Saxena mpi3mr_clear_bit(drv_cmd->dev_handle, sc->removepend_bitmap); 35122d1d418eSSumit Saxena } 35132d1d418eSSumit Saxena 35142d1d418eSSumit Saxena if (!TAILQ_EMPTY(&sc->delayed_rmhs_list)) { 35152d1d418eSSumit Saxena delayed_dev_rmhs = TAILQ_FIRST(&sc->delayed_rmhs_list); 35162d1d418eSSumit Saxena drv_cmd->dev_handle = delayed_dev_rmhs->handle; 35172d1d418eSSumit Saxena drv_cmd->retry_count = 0; 35182d1d418eSSumit Saxena drv_cmd->iou_rc = delayed_dev_rmhs->iou_rc; 35192d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_EVENT, 35202d1d418eSSumit Saxena "%s :dev_rmhs_iouctrl_complete: processing delayed TM: handle(0x%04x)\n", 35212d1d418eSSumit Saxena __func__, drv_cmd->dev_handle); 35222d1d418eSSumit Saxena mpi3mr_dev_rmhs_send_tm(sc, drv_cmd->dev_handle, drv_cmd, 35232d1d418eSSumit Saxena drv_cmd->iou_rc); 35242d1d418eSSumit Saxena TAILQ_REMOVE(&sc->delayed_rmhs_list, delayed_dev_rmhs, list); 35252d1d418eSSumit Saxena free(delayed_dev_rmhs, M_MPI3MR); 35262d1d418eSSumit Saxena return; 35272d1d418eSSumit Saxena } 35282d1d418eSSumit Saxena drv_cmd->state = MPI3MR_CMD_NOTUSED; 35292d1d418eSSumit Saxena drv_cmd->callback = NULL; 35302d1d418eSSumit Saxena drv_cmd->retry_count = 0; 35312d1d418eSSumit Saxena drv_cmd->dev_handle = MPI3MR_INVALID_DEV_HANDLE; 35322d1d418eSSumit Saxena mpi3mr_clear_bit(cmd_idx, sc->devrem_bitmap); 35332d1d418eSSumit Saxena } 35342d1d418eSSumit Saxena 35352d1d418eSSumit Saxena /** 35362d1d418eSSumit Saxena * mpi3mr_dev_rmhs_complete_tm - Device removal TM completion 35372d1d418eSSumit Saxena * @sc: Adapter instance reference 35382d1d418eSSumit Saxena * @drv_cmd: Internal command tracker 35392d1d418eSSumit Saxena * 35402d1d418eSSumit Saxena * Issues a target reset TM to the firmware from the device 35412d1d418eSSumit Saxena * removal TM pend list or issue IO Unit control request as 35422d1d418eSSumit Saxena * part of device removal or hidden acknowledgment handshake. 35432d1d418eSSumit Saxena * 35442d1d418eSSumit Saxena * Return: Nothing 35452d1d418eSSumit Saxena */ 35462d1d418eSSumit Saxena static void mpi3mr_dev_rmhs_complete_tm(struct mpi3mr_softc *sc, 35472d1d418eSSumit Saxena struct mpi3mr_drvr_cmd *drv_cmd) 35482d1d418eSSumit Saxena { 35492d1d418eSSumit Saxena Mpi3IoUnitControlRequest_t iou_ctrl; 35502d1d418eSSumit Saxena U16 cmd_idx = drv_cmd->host_tag - MPI3MR_HOSTTAG_DEVRMCMD_MIN; 35512d1d418eSSumit Saxena Mpi3SCSITaskMgmtReply_t *tm_reply = NULL; 35522d1d418eSSumit Saxena int retval; 35532d1d418eSSumit Saxena 35542d1d418eSSumit Saxena if (drv_cmd->state & MPI3MR_CMD_REPLYVALID) 35552d1d418eSSumit Saxena tm_reply = (Mpi3SCSITaskMgmtReply_t *)drv_cmd->reply; 35562d1d418eSSumit Saxena 35572d1d418eSSumit Saxena if (tm_reply) 35582d1d418eSSumit Saxena printf(IOCNAME 35592d1d418eSSumit Saxena "dev_rmhs_tr_complete:handle(0x%04x), ioc_status(0x%04x), loginfo(0x%08x), term_count(%d)\n", 35602d1d418eSSumit Saxena sc->name, drv_cmd->dev_handle, drv_cmd->ioc_status, 35612d1d418eSSumit Saxena drv_cmd->ioc_loginfo, 35622d1d418eSSumit Saxena le32toh(tm_reply->TerminationCount)); 35632d1d418eSSumit Saxena 35642d1d418eSSumit Saxena printf(IOCNAME "Issuing IOU CTL: handle(0x%04x) dev_rmhs idx(%d)\n", 35652d1d418eSSumit Saxena sc->name, drv_cmd->dev_handle, cmd_idx); 35662d1d418eSSumit Saxena 35672d1d418eSSumit Saxena memset(&iou_ctrl, 0, sizeof(iou_ctrl)); 35682d1d418eSSumit Saxena 35692d1d418eSSumit Saxena drv_cmd->state = MPI3MR_CMD_PENDING; 35702d1d418eSSumit Saxena drv_cmd->is_waiting = 0; 35712d1d418eSSumit Saxena drv_cmd->callback = mpi3mr_dev_rmhs_complete_iou; 35722d1d418eSSumit Saxena iou_ctrl.Operation = drv_cmd->iou_rc; 35732d1d418eSSumit Saxena iou_ctrl.Param16[0] = htole16(drv_cmd->dev_handle); 35742d1d418eSSumit Saxena iou_ctrl.HostTag = htole16(drv_cmd->host_tag); 35752d1d418eSSumit Saxena iou_ctrl.Function = MPI3_FUNCTION_IO_UNIT_CONTROL; 35762d1d418eSSumit Saxena 35772d1d418eSSumit Saxena retval = mpi3mr_submit_admin_cmd(sc, &iou_ctrl, sizeof(iou_ctrl)); 35782d1d418eSSumit Saxena if (retval) { 35792d1d418eSSumit Saxena printf(IOCNAME "Issue DevRmHsTMIOUCTL: Admin post failed\n", 35802d1d418eSSumit Saxena sc->name); 35812d1d418eSSumit Saxena goto out_failed; 35822d1d418eSSumit Saxena } 35832d1d418eSSumit Saxena 35842d1d418eSSumit Saxena return; 35852d1d418eSSumit Saxena out_failed: 35862d1d418eSSumit Saxena drv_cmd->state = MPI3MR_CMD_NOTUSED; 35872d1d418eSSumit Saxena drv_cmd->callback = NULL; 35882d1d418eSSumit Saxena drv_cmd->dev_handle = MPI3MR_INVALID_DEV_HANDLE; 35892d1d418eSSumit Saxena drv_cmd->retry_count = 0; 35902d1d418eSSumit Saxena mpi3mr_clear_bit(cmd_idx, sc->devrem_bitmap); 35912d1d418eSSumit Saxena } 35922d1d418eSSumit Saxena 35932d1d418eSSumit Saxena /** 35942d1d418eSSumit Saxena * mpi3mr_dev_rmhs_send_tm - Issue TM for device removal 35952d1d418eSSumit Saxena * @sc: Adapter instance reference 35962d1d418eSSumit Saxena * @handle: Device handle 35972d1d418eSSumit Saxena * @cmdparam: Internal command tracker 35982d1d418eSSumit Saxena * @iou_rc: IO Unit reason code 35992d1d418eSSumit Saxena * 36002d1d418eSSumit Saxena * Issues a target reset TM to the firmware or add it to a pend 36012d1d418eSSumit Saxena * list as part of device removal or hidden acknowledgment 36022d1d418eSSumit Saxena * handshake. 36032d1d418eSSumit Saxena * 36042d1d418eSSumit Saxena * Return: Nothing 36052d1d418eSSumit Saxena */ 36062d1d418eSSumit Saxena static void mpi3mr_dev_rmhs_send_tm(struct mpi3mr_softc *sc, U16 handle, 36072d1d418eSSumit Saxena struct mpi3mr_drvr_cmd *cmdparam, U8 iou_rc) 36082d1d418eSSumit Saxena { 36092d1d418eSSumit Saxena Mpi3SCSITaskMgmtRequest_t tm_req; 36102d1d418eSSumit Saxena int retval = 0; 36112d1d418eSSumit Saxena U16 cmd_idx = MPI3MR_NUM_DEVRMCMD; 36122d1d418eSSumit Saxena U8 retrycount = 5; 36132d1d418eSSumit Saxena struct mpi3mr_drvr_cmd *drv_cmd = cmdparam; 36142d1d418eSSumit Saxena struct delayed_dev_rmhs_node *delayed_dev_rmhs = NULL; 36152d1d418eSSumit Saxena 36162d1d418eSSumit Saxena if (drv_cmd) 36172d1d418eSSumit Saxena goto issue_cmd; 36182d1d418eSSumit Saxena do { 36192d1d418eSSumit Saxena cmd_idx = mpi3mr_find_first_zero_bit(sc->devrem_bitmap, 36202d1d418eSSumit Saxena MPI3MR_NUM_DEVRMCMD); 36212d1d418eSSumit Saxena if (cmd_idx < MPI3MR_NUM_DEVRMCMD) { 36222d1d418eSSumit Saxena if (!mpi3mr_test_and_set_bit(cmd_idx, sc->devrem_bitmap)) 36232d1d418eSSumit Saxena break; 36242d1d418eSSumit Saxena cmd_idx = MPI3MR_NUM_DEVRMCMD; 36252d1d418eSSumit Saxena } 36262d1d418eSSumit Saxena } while (retrycount--); 36272d1d418eSSumit Saxena 36282d1d418eSSumit Saxena if (cmd_idx >= MPI3MR_NUM_DEVRMCMD) { 36292d1d418eSSumit Saxena delayed_dev_rmhs = malloc(sizeof(*delayed_dev_rmhs),M_MPI3MR, 36302d1d418eSSumit Saxena M_ZERO|M_NOWAIT); 36312d1d418eSSumit Saxena 36322d1d418eSSumit Saxena if (!delayed_dev_rmhs) 36332d1d418eSSumit Saxena return; 36342d1d418eSSumit Saxena delayed_dev_rmhs->handle = handle; 36352d1d418eSSumit Saxena delayed_dev_rmhs->iou_rc = iou_rc; 36362d1d418eSSumit Saxena TAILQ_INSERT_TAIL(&(sc->delayed_rmhs_list), delayed_dev_rmhs, list); 36372d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_EVENT, "%s :DevRmHs: tr:handle(0x%04x) is postponed\n", 36382d1d418eSSumit Saxena __func__, handle); 36392d1d418eSSumit Saxena 36402d1d418eSSumit Saxena 36412d1d418eSSumit Saxena return; 36422d1d418eSSumit Saxena } 36432d1d418eSSumit Saxena drv_cmd = &sc->dev_rmhs_cmds[cmd_idx]; 36442d1d418eSSumit Saxena 36452d1d418eSSumit Saxena issue_cmd: 36462d1d418eSSumit Saxena cmd_idx = drv_cmd->host_tag - MPI3MR_HOSTTAG_DEVRMCMD_MIN; 36472d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_EVENT, 36482d1d418eSSumit Saxena "%s :Issuing TR TM: for devhandle 0x%04x with dev_rmhs %d\n", 36492d1d418eSSumit Saxena __func__, handle, cmd_idx); 36502d1d418eSSumit Saxena 36512d1d418eSSumit Saxena memset(&tm_req, 0, sizeof(tm_req)); 36522d1d418eSSumit Saxena if (drv_cmd->state & MPI3MR_CMD_PENDING) { 36532d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_EVENT, "%s :Issue TM: Command is in use\n", __func__); 36542d1d418eSSumit Saxena goto out; 36552d1d418eSSumit Saxena } 36562d1d418eSSumit Saxena drv_cmd->state = MPI3MR_CMD_PENDING; 36572d1d418eSSumit Saxena drv_cmd->is_waiting = 0; 36582d1d418eSSumit Saxena drv_cmd->callback = mpi3mr_dev_rmhs_complete_tm; 36592d1d418eSSumit Saxena drv_cmd->dev_handle = handle; 36602d1d418eSSumit Saxena drv_cmd->iou_rc = iou_rc; 36612d1d418eSSumit Saxena tm_req.DevHandle = htole16(handle); 36622d1d418eSSumit Saxena tm_req.TaskType = MPI3_SCSITASKMGMT_TASKTYPE_TARGET_RESET; 36632d1d418eSSumit Saxena tm_req.HostTag = htole16(drv_cmd->host_tag); 36642d1d418eSSumit Saxena tm_req.TaskHostTag = htole16(MPI3MR_HOSTTAG_INVALID); 36652d1d418eSSumit Saxena tm_req.Function = MPI3_FUNCTION_SCSI_TASK_MGMT; 36662d1d418eSSumit Saxena 36672d1d418eSSumit Saxena mpi3mr_set_bit(handle, sc->removepend_bitmap); 36682d1d418eSSumit Saxena retval = mpi3mr_submit_admin_cmd(sc, &tm_req, sizeof(tm_req)); 36692d1d418eSSumit Saxena if (retval) { 36702d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_ERROR, "%s :Issue DevRmHsTM: Admin Post failed\n", 36712d1d418eSSumit Saxena __func__); 36722d1d418eSSumit Saxena goto out_failed; 36732d1d418eSSumit Saxena } 36742d1d418eSSumit Saxena out: 36752d1d418eSSumit Saxena return; 36762d1d418eSSumit Saxena out_failed: 36772d1d418eSSumit Saxena drv_cmd->state = MPI3MR_CMD_NOTUSED; 36782d1d418eSSumit Saxena drv_cmd->callback = NULL; 36792d1d418eSSumit Saxena drv_cmd->dev_handle = MPI3MR_INVALID_DEV_HANDLE; 36802d1d418eSSumit Saxena drv_cmd->retry_count = 0; 36812d1d418eSSumit Saxena mpi3mr_clear_bit(cmd_idx, sc->devrem_bitmap); 36822d1d418eSSumit Saxena } 36832d1d418eSSumit Saxena 36842d1d418eSSumit Saxena /** 36852d1d418eSSumit Saxena * mpi3mr_complete_evt_ack - Event ack request completion 36862d1d418eSSumit Saxena * @sc: Adapter instance reference 36872d1d418eSSumit Saxena * @drv_cmd: Internal command tracker 36882d1d418eSSumit Saxena * 36892d1d418eSSumit Saxena * This is the completion handler for non blocking event 36902d1d418eSSumit Saxena * acknowledgment sent to the firmware and this will issue any 36912d1d418eSSumit Saxena * pending event acknowledgment request. 36922d1d418eSSumit Saxena * 36932d1d418eSSumit Saxena * Return: Nothing 36942d1d418eSSumit Saxena */ 36952d1d418eSSumit Saxena static void mpi3mr_complete_evt_ack(struct mpi3mr_softc *sc, 36962d1d418eSSumit Saxena struct mpi3mr_drvr_cmd *drv_cmd) 36972d1d418eSSumit Saxena { 36982d1d418eSSumit Saxena U16 cmd_idx = drv_cmd->host_tag - MPI3MR_HOSTTAG_EVTACKCMD_MIN; 36992d1d418eSSumit Saxena struct delayed_evtack_node *delayed_evtack = NULL; 37002d1d418eSSumit Saxena 37012d1d418eSSumit Saxena if (drv_cmd->ioc_status != MPI3_IOCSTATUS_SUCCESS) { 37022d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_EVENT, 37032d1d418eSSumit Saxena "%s: Failed IOCStatus(0x%04x) Loginfo(0x%08x)\n", __func__, 37042d1d418eSSumit Saxena (drv_cmd->ioc_status & MPI3_IOCSTATUS_STATUS_MASK), 37052d1d418eSSumit Saxena drv_cmd->ioc_loginfo); 37062d1d418eSSumit Saxena } 37072d1d418eSSumit Saxena 37082d1d418eSSumit Saxena if (!TAILQ_EMPTY(&sc->delayed_evtack_cmds_list)) { 37092d1d418eSSumit Saxena delayed_evtack = TAILQ_FIRST(&sc->delayed_evtack_cmds_list); 37102d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_EVENT, 37112d1d418eSSumit Saxena "%s: processing delayed event ack for event %d\n", 37122d1d418eSSumit Saxena __func__, delayed_evtack->event); 37132d1d418eSSumit Saxena mpi3mr_send_evt_ack(sc, delayed_evtack->event, drv_cmd, 37142d1d418eSSumit Saxena delayed_evtack->event_ctx); 37152d1d418eSSumit Saxena TAILQ_REMOVE(&sc->delayed_evtack_cmds_list, delayed_evtack, list); 37162d1d418eSSumit Saxena free(delayed_evtack, M_MPI3MR); 37172d1d418eSSumit Saxena return; 37182d1d418eSSumit Saxena } 37192d1d418eSSumit Saxena drv_cmd->state = MPI3MR_CMD_NOTUSED; 37202d1d418eSSumit Saxena drv_cmd->callback = NULL; 37212d1d418eSSumit Saxena mpi3mr_clear_bit(cmd_idx, sc->evtack_cmds_bitmap); 37222d1d418eSSumit Saxena } 37232d1d418eSSumit Saxena 37242d1d418eSSumit Saxena /** 37252d1d418eSSumit Saxena * mpi3mr_send_evt_ack - Issue event acknwoledgment request 37262d1d418eSSumit Saxena * @sc: Adapter instance reference 37272d1d418eSSumit Saxena * @event: MPI3 event id 37282d1d418eSSumit Saxena * @cmdparam: Internal command tracker 37292d1d418eSSumit Saxena * @event_ctx: Event context 37302d1d418eSSumit Saxena * 37312d1d418eSSumit Saxena * Issues event acknowledgment request to the firmware if there 37322d1d418eSSumit Saxena * is a free command to send the event ack else it to a pend 37332d1d418eSSumit Saxena * list so that it will be processed on a completion of a prior 37342d1d418eSSumit Saxena * event acknowledgment . 37352d1d418eSSumit Saxena * 37362d1d418eSSumit Saxena * Return: Nothing 37372d1d418eSSumit Saxena */ 37382d1d418eSSumit Saxena static void mpi3mr_send_evt_ack(struct mpi3mr_softc *sc, U8 event, 37392d1d418eSSumit Saxena struct mpi3mr_drvr_cmd *cmdparam, U32 event_ctx) 37402d1d418eSSumit Saxena { 37412d1d418eSSumit Saxena Mpi3EventAckRequest_t evtack_req; 37422d1d418eSSumit Saxena int retval = 0; 37432d1d418eSSumit Saxena U8 retrycount = 5; 37442d1d418eSSumit Saxena U16 cmd_idx = MPI3MR_NUM_EVTACKCMD; 37452d1d418eSSumit Saxena struct mpi3mr_drvr_cmd *drv_cmd = cmdparam; 37462d1d418eSSumit Saxena struct delayed_evtack_node *delayed_evtack = NULL; 37472d1d418eSSumit Saxena 37482d1d418eSSumit Saxena if (drv_cmd) 37492d1d418eSSumit Saxena goto issue_cmd; 37502d1d418eSSumit Saxena do { 37512d1d418eSSumit Saxena cmd_idx = mpi3mr_find_first_zero_bit(sc->evtack_cmds_bitmap, 37522d1d418eSSumit Saxena MPI3MR_NUM_EVTACKCMD); 37532d1d418eSSumit Saxena if (cmd_idx < MPI3MR_NUM_EVTACKCMD) { 37542d1d418eSSumit Saxena if (!mpi3mr_test_and_set_bit(cmd_idx, 37552d1d418eSSumit Saxena sc->evtack_cmds_bitmap)) 37562d1d418eSSumit Saxena break; 37572d1d418eSSumit Saxena cmd_idx = MPI3MR_NUM_EVTACKCMD; 37582d1d418eSSumit Saxena } 37592d1d418eSSumit Saxena } while (retrycount--); 37602d1d418eSSumit Saxena 37612d1d418eSSumit Saxena if (cmd_idx >= MPI3MR_NUM_EVTACKCMD) { 37622d1d418eSSumit Saxena delayed_evtack = malloc(sizeof(*delayed_evtack),M_MPI3MR, 37632d1d418eSSumit Saxena M_ZERO | M_NOWAIT); 37642d1d418eSSumit Saxena if (!delayed_evtack) 37652d1d418eSSumit Saxena return; 37662d1d418eSSumit Saxena delayed_evtack->event = event; 37672d1d418eSSumit Saxena delayed_evtack->event_ctx = event_ctx; 37682d1d418eSSumit Saxena TAILQ_INSERT_TAIL(&(sc->delayed_evtack_cmds_list), delayed_evtack, list); 37692d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_EVENT, "%s : Event ack for event:%d is postponed\n", 37702d1d418eSSumit Saxena __func__, event); 37712d1d418eSSumit Saxena return; 37722d1d418eSSumit Saxena } 37732d1d418eSSumit Saxena drv_cmd = &sc->evtack_cmds[cmd_idx]; 37742d1d418eSSumit Saxena 37752d1d418eSSumit Saxena issue_cmd: 37762d1d418eSSumit Saxena cmd_idx = drv_cmd->host_tag - MPI3MR_HOSTTAG_EVTACKCMD_MIN; 37772d1d418eSSumit Saxena 37782d1d418eSSumit Saxena memset(&evtack_req, 0, sizeof(evtack_req)); 37792d1d418eSSumit Saxena if (drv_cmd->state & MPI3MR_CMD_PENDING) { 37802d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_EVENT, "%s: Command is in use\n", __func__); 37812d1d418eSSumit Saxena goto out; 37822d1d418eSSumit Saxena } 37832d1d418eSSumit Saxena drv_cmd->state = MPI3MR_CMD_PENDING; 37842d1d418eSSumit Saxena drv_cmd->is_waiting = 0; 37852d1d418eSSumit Saxena drv_cmd->callback = mpi3mr_complete_evt_ack; 37862d1d418eSSumit Saxena evtack_req.HostTag = htole16(drv_cmd->host_tag); 37872d1d418eSSumit Saxena evtack_req.Function = MPI3_FUNCTION_EVENT_ACK; 37882d1d418eSSumit Saxena evtack_req.Event = event; 37892d1d418eSSumit Saxena evtack_req.EventContext = htole32(event_ctx); 37902d1d418eSSumit Saxena retval = mpi3mr_submit_admin_cmd(sc, &evtack_req, 37912d1d418eSSumit Saxena sizeof(evtack_req)); 37922d1d418eSSumit Saxena 37932d1d418eSSumit Saxena if (retval) { 37942d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_ERROR, "%s: Admin Post failed\n", __func__); 37952d1d418eSSumit Saxena goto out_failed; 37962d1d418eSSumit Saxena } 37972d1d418eSSumit Saxena out: 37982d1d418eSSumit Saxena return; 37992d1d418eSSumit Saxena out_failed: 38002d1d418eSSumit Saxena drv_cmd->state = MPI3MR_CMD_NOTUSED; 38012d1d418eSSumit Saxena drv_cmd->callback = NULL; 38022d1d418eSSumit Saxena mpi3mr_clear_bit(cmd_idx, sc->evtack_cmds_bitmap); 38032d1d418eSSumit Saxena } 38042d1d418eSSumit Saxena 38052d1d418eSSumit Saxena /* 38062d1d418eSSumit Saxena * mpi3mr_pcietopochg_evt_th - PCIETopologyChange evt tophalf 38072d1d418eSSumit Saxena * @sc: Adapter instance reference 38082d1d418eSSumit Saxena * @event_reply: Event data 38092d1d418eSSumit Saxena * 38102d1d418eSSumit Saxena * Checks for the reason code and based on that either block I/O 38112d1d418eSSumit Saxena * to device, or unblock I/O to the device, or start the device 38122d1d418eSSumit Saxena * removal handshake with reason as remove with the firmware for 38132d1d418eSSumit Saxena * PCIe devices. 38142d1d418eSSumit Saxena * 38152d1d418eSSumit Saxena * Return: Nothing 38162d1d418eSSumit Saxena */ 38172d1d418eSSumit Saxena static void mpi3mr_pcietopochg_evt_th(struct mpi3mr_softc *sc, 38182d1d418eSSumit Saxena Mpi3EventNotificationReply_t *event_reply) 38192d1d418eSSumit Saxena { 38202d1d418eSSumit Saxena Mpi3EventDataPcieTopologyChangeList_t *topo_evt = 38212d1d418eSSumit Saxena (Mpi3EventDataPcieTopologyChangeList_t *) event_reply->EventData; 38222d1d418eSSumit Saxena int i; 38232d1d418eSSumit Saxena U16 handle; 38242d1d418eSSumit Saxena U8 reason_code; 38252d1d418eSSumit Saxena struct mpi3mr_target *tgtdev = NULL; 38262d1d418eSSumit Saxena 38272d1d418eSSumit Saxena for (i = 0; i < topo_evt->NumEntries; i++) { 38282d1d418eSSumit Saxena handle = le16toh(topo_evt->PortEntry[i].AttachedDevHandle); 38292d1d418eSSumit Saxena if (!handle) 38302d1d418eSSumit Saxena continue; 38312d1d418eSSumit Saxena reason_code = topo_evt->PortEntry[i].PortStatus; 38322d1d418eSSumit Saxena tgtdev = mpi3mr_find_target_by_dev_handle(sc->cam_sc, handle); 38332d1d418eSSumit Saxena switch (reason_code) { 38342d1d418eSSumit Saxena case MPI3_EVENT_PCIE_TOPO_PS_NOT_RESPONDING: 38352d1d418eSSumit Saxena if (tgtdev) { 38362d1d418eSSumit Saxena tgtdev->dev_removed = 1; 38372d1d418eSSumit Saxena tgtdev->dev_removedelay = 0; 38382d1d418eSSumit Saxena mpi3mr_atomic_set(&tgtdev->block_io, 0); 38392d1d418eSSumit Saxena } 38402d1d418eSSumit Saxena mpi3mr_dev_rmhs_send_tm(sc, handle, NULL, 38412d1d418eSSumit Saxena MPI3_CTRL_OP_REMOVE_DEVICE); 38422d1d418eSSumit Saxena break; 38432d1d418eSSumit Saxena case MPI3_EVENT_PCIE_TOPO_PS_DELAY_NOT_RESPONDING: 38442d1d418eSSumit Saxena if (tgtdev) { 38452d1d418eSSumit Saxena tgtdev->dev_removedelay = 1; 38462d1d418eSSumit Saxena mpi3mr_atomic_inc(&tgtdev->block_io); 38472d1d418eSSumit Saxena } 38482d1d418eSSumit Saxena break; 38492d1d418eSSumit Saxena case MPI3_EVENT_PCIE_TOPO_PS_RESPONDING: 38502d1d418eSSumit Saxena if (tgtdev && 38512d1d418eSSumit Saxena tgtdev->dev_removedelay) { 38522d1d418eSSumit Saxena tgtdev->dev_removedelay = 0; 38532d1d418eSSumit Saxena if (mpi3mr_atomic_read(&tgtdev->block_io) > 0) 38542d1d418eSSumit Saxena mpi3mr_atomic_dec(&tgtdev->block_io); 38552d1d418eSSumit Saxena } 38562d1d418eSSumit Saxena break; 38572d1d418eSSumit Saxena case MPI3_EVENT_PCIE_TOPO_PS_PORT_CHANGED: 38582d1d418eSSumit Saxena default: 38592d1d418eSSumit Saxena break; 38602d1d418eSSumit Saxena } 38612d1d418eSSumit Saxena } 38622d1d418eSSumit Saxena } 38632d1d418eSSumit Saxena 38642d1d418eSSumit Saxena /** 38652d1d418eSSumit Saxena * mpi3mr_sastopochg_evt_th - SASTopologyChange evt tophalf 38662d1d418eSSumit Saxena * @sc: Adapter instance reference 38672d1d418eSSumit Saxena * @event_reply: Event data 38682d1d418eSSumit Saxena * 38692d1d418eSSumit Saxena * Checks for the reason code and based on that either block I/O 38702d1d418eSSumit Saxena * to device, or unblock I/O to the device, or start the device 38712d1d418eSSumit Saxena * removal handshake with reason as remove with the firmware for 38722d1d418eSSumit Saxena * SAS/SATA devices. 38732d1d418eSSumit Saxena * 38742d1d418eSSumit Saxena * Return: Nothing 38752d1d418eSSumit Saxena */ 38762d1d418eSSumit Saxena static void mpi3mr_sastopochg_evt_th(struct mpi3mr_softc *sc, 38772d1d418eSSumit Saxena Mpi3EventNotificationReply_t *event_reply) 38782d1d418eSSumit Saxena { 38792d1d418eSSumit Saxena Mpi3EventDataSasTopologyChangeList_t *topo_evt = 38802d1d418eSSumit Saxena (Mpi3EventDataSasTopologyChangeList_t *)event_reply->EventData; 38812d1d418eSSumit Saxena int i; 38822d1d418eSSumit Saxena U16 handle; 38832d1d418eSSumit Saxena U8 reason_code; 38842d1d418eSSumit Saxena struct mpi3mr_target *tgtdev = NULL; 38852d1d418eSSumit Saxena 38862d1d418eSSumit Saxena for (i = 0; i < topo_evt->NumEntries; i++) { 38872d1d418eSSumit Saxena handle = le16toh(topo_evt->PhyEntry[i].AttachedDevHandle); 38882d1d418eSSumit Saxena if (!handle) 38892d1d418eSSumit Saxena continue; 38902d1d418eSSumit Saxena reason_code = topo_evt->PhyEntry[i].Status & 38912d1d418eSSumit Saxena MPI3_EVENT_SAS_TOPO_PHY_RC_MASK; 38922d1d418eSSumit Saxena tgtdev = mpi3mr_find_target_by_dev_handle(sc->cam_sc, handle); 38932d1d418eSSumit Saxena switch (reason_code) { 38942d1d418eSSumit Saxena case MPI3_EVENT_SAS_TOPO_PHY_RC_TARG_NOT_RESPONDING: 38952d1d418eSSumit Saxena if (tgtdev) { 38962d1d418eSSumit Saxena tgtdev->dev_removed = 1; 38972d1d418eSSumit Saxena tgtdev->dev_removedelay = 0; 38982d1d418eSSumit Saxena mpi3mr_atomic_set(&tgtdev->block_io, 0); 38992d1d418eSSumit Saxena } 39002d1d418eSSumit Saxena mpi3mr_dev_rmhs_send_tm(sc, handle, NULL, 39012d1d418eSSumit Saxena MPI3_CTRL_OP_REMOVE_DEVICE); 39022d1d418eSSumit Saxena break; 39032d1d418eSSumit Saxena case MPI3_EVENT_SAS_TOPO_PHY_RC_DELAY_NOT_RESPONDING: 39042d1d418eSSumit Saxena if (tgtdev) { 39052d1d418eSSumit Saxena tgtdev->dev_removedelay = 1; 39062d1d418eSSumit Saxena mpi3mr_atomic_inc(&tgtdev->block_io); 39072d1d418eSSumit Saxena } 39082d1d418eSSumit Saxena break; 39092d1d418eSSumit Saxena case MPI3_EVENT_SAS_TOPO_PHY_RC_RESPONDING: 39102d1d418eSSumit Saxena if (tgtdev && 39112d1d418eSSumit Saxena tgtdev->dev_removedelay) { 39122d1d418eSSumit Saxena tgtdev->dev_removedelay = 0; 39132d1d418eSSumit Saxena if (mpi3mr_atomic_read(&tgtdev->block_io) > 0) 39142d1d418eSSumit Saxena mpi3mr_atomic_dec(&tgtdev->block_io); 39152d1d418eSSumit Saxena } 39162d1d418eSSumit Saxena case MPI3_EVENT_SAS_TOPO_PHY_RC_PHY_CHANGED: 39172d1d418eSSumit Saxena default: 39182d1d418eSSumit Saxena break; 39192d1d418eSSumit Saxena } 39202d1d418eSSumit Saxena } 39212d1d418eSSumit Saxena 39222d1d418eSSumit Saxena } 39232d1d418eSSumit Saxena /** 39242d1d418eSSumit Saxena * mpi3mr_devstatuschg_evt_th - DeviceStatusChange evt tophalf 39252d1d418eSSumit Saxena * @sc: Adapter instance reference 39262d1d418eSSumit Saxena * @event_reply: Event data 39272d1d418eSSumit Saxena * 39282d1d418eSSumit Saxena * Checks for the reason code and based on that either block I/O 39292d1d418eSSumit Saxena * to device, or unblock I/O to the device, or start the device 39302d1d418eSSumit Saxena * removal handshake with reason as remove/hide acknowledgment 39312d1d418eSSumit Saxena * with the firmware. 39322d1d418eSSumit Saxena * 39332d1d418eSSumit Saxena * Return: Nothing 39342d1d418eSSumit Saxena */ 39352d1d418eSSumit Saxena static void mpi3mr_devstatuschg_evt_th(struct mpi3mr_softc *sc, 39362d1d418eSSumit Saxena Mpi3EventNotificationReply_t *event_reply) 39372d1d418eSSumit Saxena { 39382d1d418eSSumit Saxena U16 dev_handle = 0; 39392d1d418eSSumit Saxena U8 ublock = 0, block = 0, hide = 0, uhide = 0, delete = 0, remove = 0; 39402d1d418eSSumit Saxena struct mpi3mr_target *tgtdev = NULL; 39412d1d418eSSumit Saxena Mpi3EventDataDeviceStatusChange_t *evtdata = 39422d1d418eSSumit Saxena (Mpi3EventDataDeviceStatusChange_t *) event_reply->EventData; 39432d1d418eSSumit Saxena 39442d1d418eSSumit Saxena dev_handle = le16toh(evtdata->DevHandle); 39452d1d418eSSumit Saxena 39462d1d418eSSumit Saxena switch (evtdata->ReasonCode) { 39472d1d418eSSumit Saxena case MPI3_EVENT_DEV_STAT_RC_INT_DEVICE_RESET_STRT: 39482d1d418eSSumit Saxena case MPI3_EVENT_DEV_STAT_RC_INT_IT_NEXUS_RESET_STRT: 39492d1d418eSSumit Saxena block = 1; 39502d1d418eSSumit Saxena break; 39512d1d418eSSumit Saxena case MPI3_EVENT_DEV_STAT_RC_HIDDEN: 39522d1d418eSSumit Saxena delete = 1; 39532d1d418eSSumit Saxena hide = 1; 39542d1d418eSSumit Saxena break; 39552d1d418eSSumit Saxena case MPI3_EVENT_DEV_STAT_RC_NOT_HIDDEN: 39562d1d418eSSumit Saxena uhide = 1; 39572d1d418eSSumit Saxena break; 39582d1d418eSSumit Saxena case MPI3_EVENT_DEV_STAT_RC_VD_NOT_RESPONDING: 39592d1d418eSSumit Saxena delete = 1; 39602d1d418eSSumit Saxena remove = 1; 39612d1d418eSSumit Saxena break; 39622d1d418eSSumit Saxena case MPI3_EVENT_DEV_STAT_RC_INT_DEVICE_RESET_CMP: 39632d1d418eSSumit Saxena case MPI3_EVENT_DEV_STAT_RC_INT_IT_NEXUS_RESET_CMP: 39642d1d418eSSumit Saxena ublock = 1; 39652d1d418eSSumit Saxena break; 39662d1d418eSSumit Saxena default: 39672d1d418eSSumit Saxena break; 39682d1d418eSSumit Saxena } 39692d1d418eSSumit Saxena 39702d1d418eSSumit Saxena tgtdev = mpi3mr_find_target_by_dev_handle(sc->cam_sc, dev_handle); 39712d1d418eSSumit Saxena 39722d1d418eSSumit Saxena if (!tgtdev) { 39732d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_ERROR, "%s :target with dev_handle:0x%x not found\n", 39742d1d418eSSumit Saxena __func__, dev_handle); 39752d1d418eSSumit Saxena return; 39762d1d418eSSumit Saxena } 39772d1d418eSSumit Saxena 39782d1d418eSSumit Saxena if (block) 39792d1d418eSSumit Saxena mpi3mr_atomic_inc(&tgtdev->block_io); 39802d1d418eSSumit Saxena 39812d1d418eSSumit Saxena if (hide) 39822d1d418eSSumit Saxena tgtdev->is_hidden = hide; 39832d1d418eSSumit Saxena 39842d1d418eSSumit Saxena if (uhide) { 39852d1d418eSSumit Saxena tgtdev->is_hidden = 0; 39862d1d418eSSumit Saxena tgtdev->dev_removed = 0; 39872d1d418eSSumit Saxena } 39882d1d418eSSumit Saxena 39892d1d418eSSumit Saxena if (delete) 39902d1d418eSSumit Saxena tgtdev->dev_removed = 1; 39912d1d418eSSumit Saxena 39922d1d418eSSumit Saxena if (ublock) { 39932d1d418eSSumit Saxena if (mpi3mr_atomic_read(&tgtdev->block_io) > 0) 39942d1d418eSSumit Saxena mpi3mr_atomic_dec(&tgtdev->block_io); 39952d1d418eSSumit Saxena } 39962d1d418eSSumit Saxena 39972d1d418eSSumit Saxena if (remove) { 39982d1d418eSSumit Saxena mpi3mr_dev_rmhs_send_tm(sc, dev_handle, NULL, 39992d1d418eSSumit Saxena MPI3_CTRL_OP_REMOVE_DEVICE); 40002d1d418eSSumit Saxena } 40012d1d418eSSumit Saxena if (hide) 40022d1d418eSSumit Saxena mpi3mr_dev_rmhs_send_tm(sc, dev_handle, NULL, 40032d1d418eSSumit Saxena MPI3_CTRL_OP_HIDDEN_ACK); 40042d1d418eSSumit Saxena } 40052d1d418eSSumit Saxena 40062d1d418eSSumit Saxena /** 40072d1d418eSSumit Saxena * mpi3mr_preparereset_evt_th - Prepareforreset evt tophalf 40082d1d418eSSumit Saxena * @sc: Adapter instance reference 40092d1d418eSSumit Saxena * @event_reply: Event data 40102d1d418eSSumit Saxena * 40112d1d418eSSumit Saxena * Blocks and unblocks host level I/O based on the reason code 40122d1d418eSSumit Saxena * 40132d1d418eSSumit Saxena * Return: Nothing 40142d1d418eSSumit Saxena */ 40152d1d418eSSumit Saxena static void mpi3mr_preparereset_evt_th(struct mpi3mr_softc *sc, 40162d1d418eSSumit Saxena Mpi3EventNotificationReply_t *event_reply) 40172d1d418eSSumit Saxena { 40182d1d418eSSumit Saxena Mpi3EventDataPrepareForReset_t *evtdata = 40192d1d418eSSumit Saxena (Mpi3EventDataPrepareForReset_t *)event_reply->EventData; 40202d1d418eSSumit Saxena 40212d1d418eSSumit Saxena if (evtdata->ReasonCode == MPI3_EVENT_PREPARE_RESET_RC_START) { 40222d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_EVENT, "%s :Recieved PrepForReset Event with RC=START\n", 40232d1d418eSSumit Saxena __func__); 40242d1d418eSSumit Saxena if (sc->prepare_for_reset) 40252d1d418eSSumit Saxena return; 40262d1d418eSSumit Saxena sc->prepare_for_reset = 1; 40272d1d418eSSumit Saxena sc->prepare_for_reset_timeout_counter = 0; 40282d1d418eSSumit Saxena } else if (evtdata->ReasonCode == MPI3_EVENT_PREPARE_RESET_RC_ABORT) { 40292d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_EVENT, "%s :Recieved PrepForReset Event with RC=ABORT\n", 40302d1d418eSSumit Saxena __func__); 40312d1d418eSSumit Saxena sc->prepare_for_reset = 0; 40322d1d418eSSumit Saxena sc->prepare_for_reset_timeout_counter = 0; 40332d1d418eSSumit Saxena } 40342d1d418eSSumit Saxena if ((event_reply->MsgFlags & MPI3_EVENT_NOTIFY_MSGFLAGS_ACK_MASK) 40352d1d418eSSumit Saxena == MPI3_EVENT_NOTIFY_MSGFLAGS_ACK_REQUIRED) 40362d1d418eSSumit Saxena mpi3mr_send_evt_ack(sc, event_reply->Event, NULL, 40372d1d418eSSumit Saxena le32toh(event_reply->EventContext)); 40382d1d418eSSumit Saxena } 40392d1d418eSSumit Saxena 40402d1d418eSSumit Saxena /** 40412d1d418eSSumit Saxena * mpi3mr_energypackchg_evt_th - Energypackchange evt tophalf 40422d1d418eSSumit Saxena * @sc: Adapter instance reference 40432d1d418eSSumit Saxena * @event_reply: Event data 40442d1d418eSSumit Saxena * 40452d1d418eSSumit Saxena * Identifies the new shutdown timeout value and update. 40462d1d418eSSumit Saxena * 40472d1d418eSSumit Saxena * Return: Nothing 40482d1d418eSSumit Saxena */ 40492d1d418eSSumit Saxena static void mpi3mr_energypackchg_evt_th(struct mpi3mr_softc *sc, 40502d1d418eSSumit Saxena Mpi3EventNotificationReply_t *event_reply) 40512d1d418eSSumit Saxena { 40522d1d418eSSumit Saxena Mpi3EventDataEnergyPackChange_t *evtdata = 40532d1d418eSSumit Saxena (Mpi3EventDataEnergyPackChange_t *)event_reply->EventData; 40542d1d418eSSumit Saxena U16 shutdown_timeout = le16toh(evtdata->ShutdownTimeout); 40552d1d418eSSumit Saxena 40562d1d418eSSumit Saxena if (shutdown_timeout <= 0) { 40572d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_ERROR, 40582d1d418eSSumit Saxena "%s :Invalid Shutdown Timeout received = %d\n", 40592d1d418eSSumit Saxena __func__, shutdown_timeout); 40602d1d418eSSumit Saxena return; 40612d1d418eSSumit Saxena } 40622d1d418eSSumit Saxena 40632d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_EVENT, 40642d1d418eSSumit Saxena "%s :Previous Shutdown Timeout Value = %d New Shutdown Timeout Value = %d\n", 40652d1d418eSSumit Saxena __func__, sc->facts.shutdown_timeout, shutdown_timeout); 40662d1d418eSSumit Saxena sc->facts.shutdown_timeout = shutdown_timeout; 40672d1d418eSSumit Saxena } 40682d1d418eSSumit Saxena 40692d1d418eSSumit Saxena /** 40702d1d418eSSumit Saxena * mpi3mr_cablemgmt_evt_th - Cable mgmt evt tophalf 40712d1d418eSSumit Saxena * @sc: Adapter instance reference 40722d1d418eSSumit Saxena * @event_reply: Event data 40732d1d418eSSumit Saxena * 40742d1d418eSSumit Saxena * Displays Cable manegemt event details. 40752d1d418eSSumit Saxena * 40762d1d418eSSumit Saxena * Return: Nothing 40772d1d418eSSumit Saxena */ 40782d1d418eSSumit Saxena static void mpi3mr_cablemgmt_evt_th(struct mpi3mr_softc *sc, 40792d1d418eSSumit Saxena Mpi3EventNotificationReply_t *event_reply) 40802d1d418eSSumit Saxena { 40812d1d418eSSumit Saxena Mpi3EventDataCableManagement_t *evtdata = 40822d1d418eSSumit Saxena (Mpi3EventDataCableManagement_t *)event_reply->EventData; 40832d1d418eSSumit Saxena 40842d1d418eSSumit Saxena switch (evtdata->Status) { 40852d1d418eSSumit Saxena case MPI3_EVENT_CABLE_MGMT_STATUS_INSUFFICIENT_POWER: 40862d1d418eSSumit Saxena { 40872d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_INFO, "An active cable with ReceptacleID %d cannot be powered.\n" 40882d1d418eSSumit Saxena "Devices connected to this cable are not detected.\n" 40892d1d418eSSumit Saxena "This cable requires %d mW of power.\n", 40902d1d418eSSumit Saxena evtdata->ReceptacleID, 40912d1d418eSSumit Saxena le32toh(evtdata->ActiveCablePowerRequirement)); 40922d1d418eSSumit Saxena break; 40932d1d418eSSumit Saxena } 40942d1d418eSSumit Saxena case MPI3_EVENT_CABLE_MGMT_STATUS_DEGRADED: 40952d1d418eSSumit Saxena { 40962d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_INFO, "A cable with ReceptacleID %d is not running at optimal speed\n", 40972d1d418eSSumit Saxena evtdata->ReceptacleID); 40982d1d418eSSumit Saxena break; 40992d1d418eSSumit Saxena } 41002d1d418eSSumit Saxena default: 41012d1d418eSSumit Saxena break; 41022d1d418eSSumit Saxena } 41032d1d418eSSumit Saxena } 41042d1d418eSSumit Saxena 41052d1d418eSSumit Saxena /** 41062d1d418eSSumit Saxena * mpi3mr_process_events - Event's toph-half handler 41072d1d418eSSumit Saxena * @sc: Adapter instance reference 41082d1d418eSSumit Saxena * @event_reply: Event data 41092d1d418eSSumit Saxena * 41102d1d418eSSumit Saxena * Top half of event processing. 41112d1d418eSSumit Saxena * 41122d1d418eSSumit Saxena * Return: Nothing 41132d1d418eSSumit Saxena */ 41142d1d418eSSumit Saxena static void mpi3mr_process_events(struct mpi3mr_softc *sc, 41152d1d418eSSumit Saxena uintptr_t data, Mpi3EventNotificationReply_t *event_reply) 41162d1d418eSSumit Saxena { 41172d1d418eSSumit Saxena U16 evt_type; 41182d1d418eSSumit Saxena bool ack_req = 0, process_evt_bh = 0; 41192d1d418eSSumit Saxena struct mpi3mr_fw_event_work *fw_event; 41202d1d418eSSumit Saxena U16 sz; 41212d1d418eSSumit Saxena 41222d1d418eSSumit Saxena if (sc->mpi3mr_flags & MPI3MR_FLAGS_SHUTDOWN) 41232d1d418eSSumit Saxena goto out; 41242d1d418eSSumit Saxena 41252d1d418eSSumit Saxena if ((event_reply->MsgFlags & MPI3_EVENT_NOTIFY_MSGFLAGS_ACK_MASK) 41262d1d418eSSumit Saxena == MPI3_EVENT_NOTIFY_MSGFLAGS_ACK_REQUIRED) 41272d1d418eSSumit Saxena ack_req = 1; 41282d1d418eSSumit Saxena 41292d1d418eSSumit Saxena evt_type = event_reply->Event; 41302d1d418eSSumit Saxena 41312d1d418eSSumit Saxena switch (evt_type) { 41322d1d418eSSumit Saxena case MPI3_EVENT_DEVICE_ADDED: 41332d1d418eSSumit Saxena { 41342d1d418eSSumit Saxena Mpi3DevicePage0_t *dev_pg0 = 41352d1d418eSSumit Saxena (Mpi3DevicePage0_t *) event_reply->EventData; 41362d1d418eSSumit Saxena if (mpi3mr_create_device(sc, dev_pg0)) 41372d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_ERROR, 41382d1d418eSSumit Saxena "%s :Failed to add device in the device add event\n", 41392d1d418eSSumit Saxena __func__); 41402d1d418eSSumit Saxena else 41412d1d418eSSumit Saxena process_evt_bh = 1; 41422d1d418eSSumit Saxena break; 41432d1d418eSSumit Saxena } 41442d1d418eSSumit Saxena 41452d1d418eSSumit Saxena case MPI3_EVENT_DEVICE_STATUS_CHANGE: 41462d1d418eSSumit Saxena { 41472d1d418eSSumit Saxena process_evt_bh = 1; 41482d1d418eSSumit Saxena mpi3mr_devstatuschg_evt_th(sc, event_reply); 41492d1d418eSSumit Saxena break; 41502d1d418eSSumit Saxena } 41512d1d418eSSumit Saxena case MPI3_EVENT_SAS_TOPOLOGY_CHANGE_LIST: 41522d1d418eSSumit Saxena { 41532d1d418eSSumit Saxena process_evt_bh = 1; 41542d1d418eSSumit Saxena mpi3mr_sastopochg_evt_th(sc, event_reply); 41552d1d418eSSumit Saxena break; 41562d1d418eSSumit Saxena } 41572d1d418eSSumit Saxena case MPI3_EVENT_PCIE_TOPOLOGY_CHANGE_LIST: 41582d1d418eSSumit Saxena { 41592d1d418eSSumit Saxena process_evt_bh = 1; 41602d1d418eSSumit Saxena mpi3mr_pcietopochg_evt_th(sc, event_reply); 41612d1d418eSSumit Saxena break; 41622d1d418eSSumit Saxena } 41632d1d418eSSumit Saxena case MPI3_EVENT_PREPARE_FOR_RESET: 41642d1d418eSSumit Saxena { 41652d1d418eSSumit Saxena mpi3mr_preparereset_evt_th(sc, event_reply); 41662d1d418eSSumit Saxena ack_req = 0; 41672d1d418eSSumit Saxena break; 41682d1d418eSSumit Saxena } 41692d1d418eSSumit Saxena case MPI3_EVENT_DEVICE_INFO_CHANGED: 41702d1d418eSSumit Saxena case MPI3_EVENT_LOG_DATA: 41712d1d418eSSumit Saxena { 41722d1d418eSSumit Saxena process_evt_bh = 1; 41732d1d418eSSumit Saxena break; 41742d1d418eSSumit Saxena } 41752d1d418eSSumit Saxena case MPI3_EVENT_ENERGY_PACK_CHANGE: 41762d1d418eSSumit Saxena { 41772d1d418eSSumit Saxena mpi3mr_energypackchg_evt_th(sc, event_reply); 41782d1d418eSSumit Saxena break; 41792d1d418eSSumit Saxena } 41802d1d418eSSumit Saxena case MPI3_EVENT_CABLE_MGMT: 41812d1d418eSSumit Saxena { 41822d1d418eSSumit Saxena mpi3mr_cablemgmt_evt_th(sc, event_reply); 41832d1d418eSSumit Saxena break; 41842d1d418eSSumit Saxena } 41852d1d418eSSumit Saxena 41862d1d418eSSumit Saxena case MPI3_EVENT_ENCL_DEVICE_STATUS_CHANGE: 41872d1d418eSSumit Saxena case MPI3_EVENT_SAS_DISCOVERY: 41882d1d418eSSumit Saxena case MPI3_EVENT_SAS_DEVICE_DISCOVERY_ERROR: 41892d1d418eSSumit Saxena case MPI3_EVENT_SAS_BROADCAST_PRIMITIVE: 41902d1d418eSSumit Saxena case MPI3_EVENT_PCIE_ENUMERATION: 41912d1d418eSSumit Saxena break; 41922d1d418eSSumit Saxena default: 41932d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_INFO, "%s :Event 0x%02x is not handled by driver\n", 41942d1d418eSSumit Saxena __func__, evt_type); 41952d1d418eSSumit Saxena break; 41962d1d418eSSumit Saxena } 41972d1d418eSSumit Saxena 41982d1d418eSSumit Saxena if (process_evt_bh || ack_req) { 41992d1d418eSSumit Saxena fw_event = malloc(sizeof(struct mpi3mr_fw_event_work), M_MPI3MR, 42002d1d418eSSumit Saxena M_ZERO|M_NOWAIT); 42012d1d418eSSumit Saxena 42022d1d418eSSumit Saxena if (!fw_event) { 42032d1d418eSSumit Saxena printf("%s: allocate failed for fw_event\n", __func__); 42042d1d418eSSumit Saxena return; 42052d1d418eSSumit Saxena } 42062d1d418eSSumit Saxena 42072d1d418eSSumit Saxena sz = le16toh(event_reply->EventDataLength) * 4; 42082d1d418eSSumit Saxena fw_event->event_data = malloc(sz, M_MPI3MR, M_ZERO|M_NOWAIT); 42092d1d418eSSumit Saxena 42102d1d418eSSumit Saxena if (!fw_event->event_data) { 42112d1d418eSSumit Saxena printf("%s: allocate failed for event_data\n", __func__); 42122d1d418eSSumit Saxena free(fw_event, M_MPI3MR); 42132d1d418eSSumit Saxena return; 42142d1d418eSSumit Saxena } 42152d1d418eSSumit Saxena 42162d1d418eSSumit Saxena bcopy(event_reply->EventData, fw_event->event_data, sz); 42172d1d418eSSumit Saxena fw_event->event = event_reply->Event; 42182d1d418eSSumit Saxena if ((event_reply->Event == MPI3_EVENT_SAS_TOPOLOGY_CHANGE_LIST || 42192d1d418eSSumit Saxena event_reply->Event == MPI3_EVENT_PCIE_TOPOLOGY_CHANGE_LIST || 42202d1d418eSSumit Saxena event_reply->Event == MPI3_EVENT_ENCL_DEVICE_STATUS_CHANGE ) && 42212d1d418eSSumit Saxena sc->track_mapping_events) 42222d1d418eSSumit Saxena sc->pending_map_events++; 42232d1d418eSSumit Saxena 42242d1d418eSSumit Saxena /* 42252d1d418eSSumit Saxena * Events should be processed after Port enable is completed. 42262d1d418eSSumit Saxena */ 42272d1d418eSSumit Saxena if ((event_reply->Event == MPI3_EVENT_SAS_TOPOLOGY_CHANGE_LIST || 42282d1d418eSSumit Saxena event_reply->Event == MPI3_EVENT_PCIE_TOPOLOGY_CHANGE_LIST ) && 42292d1d418eSSumit Saxena !(sc->mpi3mr_flags & MPI3MR_FLAGS_PORT_ENABLE_DONE)) 42302d1d418eSSumit Saxena mpi3mr_startup_increment(sc->cam_sc); 42312d1d418eSSumit Saxena 42322d1d418eSSumit Saxena fw_event->send_ack = ack_req; 42332d1d418eSSumit Saxena fw_event->event_context = le32toh(event_reply->EventContext); 42342d1d418eSSumit Saxena fw_event->event_data_size = sz; 42352d1d418eSSumit Saxena fw_event->process_event = process_evt_bh; 42362d1d418eSSumit Saxena 42372d1d418eSSumit Saxena mtx_lock(&sc->fwevt_lock); 42382d1d418eSSumit Saxena TAILQ_INSERT_TAIL(&sc->cam_sc->ev_queue, fw_event, ev_link); 42392d1d418eSSumit Saxena taskqueue_enqueue(sc->cam_sc->ev_tq, &sc->cam_sc->ev_task); 42402d1d418eSSumit Saxena mtx_unlock(&sc->fwevt_lock); 42412d1d418eSSumit Saxena 42422d1d418eSSumit Saxena } 42432d1d418eSSumit Saxena out: 42442d1d418eSSumit Saxena return; 42452d1d418eSSumit Saxena } 42462d1d418eSSumit Saxena 42472d1d418eSSumit Saxena static void mpi3mr_handle_events(struct mpi3mr_softc *sc, uintptr_t data, 42482d1d418eSSumit Saxena Mpi3DefaultReply_t *def_reply) 42492d1d418eSSumit Saxena { 42502d1d418eSSumit Saxena Mpi3EventNotificationReply_t *event_reply = 42512d1d418eSSumit Saxena (Mpi3EventNotificationReply_t *)def_reply; 42522d1d418eSSumit Saxena 42532d1d418eSSumit Saxena sc->change_count = event_reply->IOCChangeCount; 42542d1d418eSSumit Saxena mpi3mr_display_event_data(sc, event_reply); 42552d1d418eSSumit Saxena 42562d1d418eSSumit Saxena mpi3mr_process_events(sc, data, event_reply); 42572d1d418eSSumit Saxena } 42582d1d418eSSumit Saxena 42592d1d418eSSumit Saxena static void mpi3mr_process_admin_reply_desc(struct mpi3mr_softc *sc, 42602d1d418eSSumit Saxena Mpi3DefaultReplyDescriptor_t *reply_desc, U64 *reply_dma) 42612d1d418eSSumit Saxena { 42622d1d418eSSumit Saxena U16 reply_desc_type, host_tag = 0, idx; 42632d1d418eSSumit Saxena U16 ioc_status = MPI3_IOCSTATUS_SUCCESS; 42642d1d418eSSumit Saxena U32 ioc_loginfo = 0; 42652d1d418eSSumit Saxena Mpi3StatusReplyDescriptor_t *status_desc; 42662d1d418eSSumit Saxena Mpi3AddressReplyDescriptor_t *addr_desc; 42672d1d418eSSumit Saxena Mpi3SuccessReplyDescriptor_t *success_desc; 42682d1d418eSSumit Saxena Mpi3DefaultReply_t *def_reply = NULL; 42692d1d418eSSumit Saxena struct mpi3mr_drvr_cmd *cmdptr = NULL; 42702d1d418eSSumit Saxena Mpi3SCSIIOReply_t *scsi_reply; 42712d1d418eSSumit Saxena U8 *sense_buf = NULL; 42722d1d418eSSumit Saxena 42732d1d418eSSumit Saxena *reply_dma = 0; 42742d1d418eSSumit Saxena reply_desc_type = reply_desc->ReplyFlags & 42752d1d418eSSumit Saxena MPI3_REPLY_DESCRIPT_FLAGS_TYPE_MASK; 42762d1d418eSSumit Saxena switch (reply_desc_type) { 42772d1d418eSSumit Saxena case MPI3_REPLY_DESCRIPT_FLAGS_TYPE_STATUS: 42782d1d418eSSumit Saxena status_desc = (Mpi3StatusReplyDescriptor_t *)reply_desc; 42792d1d418eSSumit Saxena host_tag = status_desc->HostTag; 42802d1d418eSSumit Saxena ioc_status = status_desc->IOCStatus; 42812d1d418eSSumit Saxena if (ioc_status & 42822d1d418eSSumit Saxena MPI3_REPLY_DESCRIPT_STATUS_IOCSTATUS_LOGINFOAVAIL) 42832d1d418eSSumit Saxena ioc_loginfo = status_desc->IOCLogInfo; 42842d1d418eSSumit Saxena ioc_status &= MPI3_REPLY_DESCRIPT_STATUS_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; 42942d1d418eSSumit Saxena if (ioc_status & 42952d1d418eSSumit Saxena MPI3_REPLY_DESCRIPT_STATUS_IOCSTATUS_LOGINFOAVAIL) 42962d1d418eSSumit Saxena ioc_loginfo = def_reply->IOCLogInfo; 42972d1d418eSSumit Saxena ioc_status &= MPI3_REPLY_DESCRIPT_STATUS_IOCSTATUS_STATUS_MASK; 42982d1d418eSSumit Saxena if (def_reply->Function == MPI3_FUNCTION_SCSI_IO) { 42992d1d418eSSumit Saxena scsi_reply = (Mpi3SCSIIOReply_t *)def_reply; 43002d1d418eSSumit Saxena sense_buf = mpi3mr_get_sensebuf_virt_addr(sc, 43012d1d418eSSumit Saxena scsi_reply->SenseDataBufferAddress); 43022d1d418eSSumit Saxena } 43032d1d418eSSumit Saxena break; 43042d1d418eSSumit Saxena case MPI3_REPLY_DESCRIPT_FLAGS_TYPE_SUCCESS: 43052d1d418eSSumit Saxena success_desc = (Mpi3SuccessReplyDescriptor_t *)reply_desc; 43062d1d418eSSumit Saxena host_tag = success_desc->HostTag; 43072d1d418eSSumit Saxena break; 43082d1d418eSSumit Saxena default: 43092d1d418eSSumit Saxena break; 43102d1d418eSSumit Saxena } 43112d1d418eSSumit Saxena switch (host_tag) { 43122d1d418eSSumit Saxena case MPI3MR_HOSTTAG_INITCMDS: 43132d1d418eSSumit Saxena cmdptr = &sc->init_cmds; 43142d1d418eSSumit Saxena break; 43152d1d418eSSumit Saxena case MPI3MR_HOSTTAG_IOCTLCMDS: 43162d1d418eSSumit Saxena cmdptr = &sc->ioctl_cmds; 43172d1d418eSSumit Saxena break; 43182d1d418eSSumit Saxena case MPI3MR_HOSTTAG_TMS: 43192d1d418eSSumit Saxena cmdptr = &sc->host_tm_cmds; 43202d1d418eSSumit Saxena wakeup((void *)&sc->tm_chan); 43212d1d418eSSumit Saxena break; 43222d1d418eSSumit Saxena case MPI3MR_HOSTTAG_PELABORT: 43232d1d418eSSumit Saxena cmdptr = &sc->pel_abort_cmd; 43242d1d418eSSumit Saxena break; 43252d1d418eSSumit Saxena case MPI3MR_HOSTTAG_PELWAIT: 43262d1d418eSSumit Saxena cmdptr = &sc->pel_cmds; 43272d1d418eSSumit Saxena break; 43282d1d418eSSumit Saxena case MPI3MR_HOSTTAG_INVALID: 43292d1d418eSSumit Saxena if (def_reply && def_reply->Function == 43302d1d418eSSumit Saxena MPI3_FUNCTION_EVENT_NOTIFICATION) 43312d1d418eSSumit Saxena mpi3mr_handle_events(sc, *reply_dma ,def_reply); 43322d1d418eSSumit Saxena default: 43332d1d418eSSumit Saxena break; 43342d1d418eSSumit Saxena } 43352d1d418eSSumit Saxena 43362d1d418eSSumit Saxena if (host_tag >= MPI3MR_HOSTTAG_DEVRMCMD_MIN && 43372d1d418eSSumit Saxena host_tag <= MPI3MR_HOSTTAG_DEVRMCMD_MAX ) { 43382d1d418eSSumit Saxena idx = host_tag - MPI3MR_HOSTTAG_DEVRMCMD_MIN; 43392d1d418eSSumit Saxena cmdptr = &sc->dev_rmhs_cmds[idx]; 43402d1d418eSSumit Saxena } 43412d1d418eSSumit Saxena 43422d1d418eSSumit Saxena if (host_tag >= MPI3MR_HOSTTAG_EVTACKCMD_MIN && 43432d1d418eSSumit Saxena host_tag <= MPI3MR_HOSTTAG_EVTACKCMD_MAX) { 43442d1d418eSSumit Saxena idx = host_tag - MPI3MR_HOSTTAG_EVTACKCMD_MIN; 43452d1d418eSSumit Saxena cmdptr = &sc->evtack_cmds[idx]; 43462d1d418eSSumit Saxena } 43472d1d418eSSumit Saxena 43482d1d418eSSumit Saxena if (cmdptr) { 43492d1d418eSSumit Saxena if (cmdptr->state & MPI3MR_CMD_PENDING) { 43502d1d418eSSumit Saxena cmdptr->state |= MPI3MR_CMD_COMPLETE; 43512d1d418eSSumit Saxena cmdptr->ioc_loginfo = ioc_loginfo; 43522d1d418eSSumit Saxena cmdptr->ioc_status = ioc_status; 43532d1d418eSSumit Saxena cmdptr->state &= ~MPI3MR_CMD_PENDING; 43542d1d418eSSumit Saxena if (def_reply) { 43552d1d418eSSumit Saxena cmdptr->state |= MPI3MR_CMD_REPLYVALID; 43562d1d418eSSumit Saxena memcpy((U8 *)cmdptr->reply, (U8 *)def_reply, 43572d1d418eSSumit Saxena sc->reply_sz); 43582d1d418eSSumit Saxena } 43592d1d418eSSumit Saxena if (sense_buf && cmdptr->sensebuf) { 43602d1d418eSSumit Saxena cmdptr->is_senseprst = 1; 43612d1d418eSSumit Saxena memcpy(cmdptr->sensebuf, sense_buf, 43622d1d418eSSumit Saxena MPI3MR_SENSEBUF_SZ); 43632d1d418eSSumit Saxena } 43642d1d418eSSumit Saxena if (cmdptr->is_waiting) { 43652d1d418eSSumit Saxena complete(&cmdptr->completion); 43662d1d418eSSumit Saxena cmdptr->is_waiting = 0; 43672d1d418eSSumit Saxena } else if (cmdptr->callback) 43682d1d418eSSumit Saxena cmdptr->callback(sc, cmdptr); 43692d1d418eSSumit Saxena } 43702d1d418eSSumit Saxena } 43712d1d418eSSumit Saxena out: 43722d1d418eSSumit Saxena if (sense_buf != NULL) 43732d1d418eSSumit Saxena mpi3mr_repost_sense_buf(sc, 43742d1d418eSSumit Saxena scsi_reply->SenseDataBufferAddress); 43752d1d418eSSumit Saxena return; 43762d1d418eSSumit Saxena } 43772d1d418eSSumit Saxena 43782d1d418eSSumit Saxena /* 43792d1d418eSSumit Saxena * mpi3mr_complete_admin_cmd: ISR routine for admin commands 43802d1d418eSSumit Saxena * @sc: Adapter's soft instance 43812d1d418eSSumit Saxena * 43822d1d418eSSumit Saxena * This function processes admin command completions. 43832d1d418eSSumit Saxena */ 43842d1d418eSSumit Saxena static int mpi3mr_complete_admin_cmd(struct mpi3mr_softc *sc) 43852d1d418eSSumit Saxena { 43862d1d418eSSumit Saxena U32 exp_phase = sc->admin_reply_ephase; 43872d1d418eSSumit Saxena U32 adm_reply_ci = sc->admin_reply_ci; 43882d1d418eSSumit Saxena U32 num_adm_reply = 0; 43892d1d418eSSumit Saxena U64 reply_dma = 0; 43902d1d418eSSumit Saxena Mpi3DefaultReplyDescriptor_t *reply_desc; 4391*eb7a4b35SChandrakanth patil U16 threshold_comps = 0; 43922d1d418eSSumit Saxena 43932d1d418eSSumit Saxena mtx_lock_spin(&sc->admin_reply_lock); 43942d1d418eSSumit Saxena if (sc->admin_in_use == false) { 43952d1d418eSSumit Saxena sc->admin_in_use = true; 43962d1d418eSSumit Saxena mtx_unlock_spin(&sc->admin_reply_lock); 43972d1d418eSSumit Saxena } else { 43982d1d418eSSumit Saxena mtx_unlock_spin(&sc->admin_reply_lock); 43992d1d418eSSumit Saxena return 0; 44002d1d418eSSumit Saxena } 44012d1d418eSSumit Saxena 44022d1d418eSSumit Saxena reply_desc = (Mpi3DefaultReplyDescriptor_t *)sc->admin_reply + 44032d1d418eSSumit Saxena adm_reply_ci; 44042d1d418eSSumit Saxena 44052d1d418eSSumit Saxena if ((reply_desc->ReplyFlags & 44062d1d418eSSumit Saxena MPI3_REPLY_DESCRIPT_FLAGS_PHASE_MASK) != exp_phase) { 44072d1d418eSSumit Saxena mtx_lock_spin(&sc->admin_reply_lock); 44082d1d418eSSumit Saxena sc->admin_in_use = false; 44092d1d418eSSumit Saxena mtx_unlock_spin(&sc->admin_reply_lock); 44102d1d418eSSumit Saxena return 0; 44112d1d418eSSumit Saxena } 44122d1d418eSSumit Saxena 44132d1d418eSSumit Saxena do { 44142d1d418eSSumit Saxena sc->admin_req_ci = reply_desc->RequestQueueCI; 44152d1d418eSSumit Saxena mpi3mr_process_admin_reply_desc(sc, reply_desc, &reply_dma); 44162d1d418eSSumit Saxena if (reply_dma) 44172d1d418eSSumit Saxena mpi3mr_repost_reply_buf(sc, reply_dma); 44182d1d418eSSumit Saxena num_adm_reply++; 44192d1d418eSSumit Saxena if (++adm_reply_ci == sc->num_admin_replies) { 44202d1d418eSSumit Saxena adm_reply_ci = 0; 44212d1d418eSSumit Saxena exp_phase ^= 1; 44222d1d418eSSumit Saxena } 44232d1d418eSSumit Saxena reply_desc = 44242d1d418eSSumit Saxena (Mpi3DefaultReplyDescriptor_t *)sc->admin_reply + 44252d1d418eSSumit Saxena adm_reply_ci; 44262d1d418eSSumit Saxena if ((reply_desc->ReplyFlags & 44272d1d418eSSumit Saxena MPI3_REPLY_DESCRIPT_FLAGS_PHASE_MASK) != exp_phase) 44282d1d418eSSumit Saxena break; 4429*eb7a4b35SChandrakanth patil 4430*eb7a4b35SChandrakanth patil if (++threshold_comps == MPI3MR_THRESHOLD_REPLY_COUNT) { 4431*eb7a4b35SChandrakanth patil mpi3mr_regwrite(sc, MPI3_SYSIF_ADMIN_REPLY_Q_CI_OFFSET, adm_reply_ci); 4432*eb7a4b35SChandrakanth patil threshold_comps = 0; 4433*eb7a4b35SChandrakanth patil } 44342d1d418eSSumit Saxena } while (1); 44352d1d418eSSumit Saxena 44362d1d418eSSumit Saxena mpi3mr_regwrite(sc, MPI3_SYSIF_ADMIN_REPLY_Q_CI_OFFSET, adm_reply_ci); 44372d1d418eSSumit Saxena sc->admin_reply_ci = adm_reply_ci; 44382d1d418eSSumit Saxena sc->admin_reply_ephase = exp_phase; 44392d1d418eSSumit Saxena mtx_lock_spin(&sc->admin_reply_lock); 44402d1d418eSSumit Saxena sc->admin_in_use = false; 44412d1d418eSSumit Saxena mtx_unlock_spin(&sc->admin_reply_lock); 44422d1d418eSSumit Saxena return num_adm_reply; 44432d1d418eSSumit Saxena } 44442d1d418eSSumit Saxena 44452d1d418eSSumit Saxena static void 44462d1d418eSSumit Saxena mpi3mr_cmd_done(struct mpi3mr_softc *sc, struct mpi3mr_cmd *cmd) 44472d1d418eSSumit Saxena { 44482d1d418eSSumit Saxena mpi3mr_unmap_request(sc, cmd); 44492d1d418eSSumit Saxena 44502d1d418eSSumit Saxena mtx_lock(&sc->mpi3mr_mtx); 44512d1d418eSSumit Saxena if (cmd->callout_owner) { 44522d1d418eSSumit Saxena callout_stop(&cmd->callout); 44532d1d418eSSumit Saxena cmd->callout_owner = false; 44542d1d418eSSumit Saxena } 44552d1d418eSSumit Saxena 44562d1d418eSSumit Saxena if (sc->unrecoverable) 44572d1d418eSSumit Saxena mpi3mr_set_ccbstatus(cmd->ccb, CAM_DEV_NOT_THERE); 44582d1d418eSSumit Saxena 44592d1d418eSSumit Saxena xpt_done(cmd->ccb); 44602d1d418eSSumit Saxena cmd->ccb = NULL; 44612d1d418eSSumit Saxena mtx_unlock(&sc->mpi3mr_mtx); 44622d1d418eSSumit Saxena mpi3mr_release_command(cmd); 44632d1d418eSSumit Saxena } 44642d1d418eSSumit Saxena 44652d1d418eSSumit Saxena void mpi3mr_process_op_reply_desc(struct mpi3mr_softc *sc, 44662d1d418eSSumit Saxena Mpi3DefaultReplyDescriptor_t *reply_desc, U64 *reply_dma) 44672d1d418eSSumit Saxena { 44682d1d418eSSumit Saxena U16 reply_desc_type, host_tag = 0; 44692d1d418eSSumit Saxena U16 ioc_status = MPI3_IOCSTATUS_SUCCESS; 44702d1d418eSSumit Saxena U32 ioc_loginfo = 0; 44712d1d418eSSumit Saxena Mpi3StatusReplyDescriptor_t *status_desc = NULL; 44722d1d418eSSumit Saxena Mpi3AddressReplyDescriptor_t *addr_desc = NULL; 44732d1d418eSSumit Saxena Mpi3SuccessReplyDescriptor_t *success_desc = NULL; 44742d1d418eSSumit Saxena Mpi3SCSIIOReply_t *scsi_reply = NULL; 44752d1d418eSSumit Saxena U8 *sense_buf = NULL; 44762d1d418eSSumit Saxena U8 scsi_state = 0, scsi_status = 0, sense_state = 0; 44772d1d418eSSumit Saxena U32 xfer_count = 0, sense_count =0, resp_data = 0; 44782d1d418eSSumit Saxena struct mpi3mr_cmd *cm = NULL; 44792d1d418eSSumit Saxena union ccb *ccb; 44802d1d418eSSumit Saxena struct ccb_scsiio *csio; 44812d1d418eSSumit Saxena struct mpi3mr_cam_softc *cam_sc; 44822d1d418eSSumit Saxena U32 target_id; 44832d1d418eSSumit Saxena U8 *scsi_cdb; 44842d1d418eSSumit Saxena struct mpi3mr_target *target = NULL; 44852d1d418eSSumit Saxena U32 ioc_pend_data_len = 0, tg_pend_data_len = 0, data_len_blks = 0; 44862d1d418eSSumit Saxena struct mpi3mr_throttle_group_info *tg = NULL; 44872d1d418eSSumit Saxena U8 throttle_enabled_dev = 0; 44882d1d418eSSumit Saxena static int ratelimit; 44892d1d418eSSumit Saxena 44902d1d418eSSumit Saxena *reply_dma = 0; 44912d1d418eSSumit Saxena reply_desc_type = reply_desc->ReplyFlags & 44922d1d418eSSumit Saxena MPI3_REPLY_DESCRIPT_FLAGS_TYPE_MASK; 44932d1d418eSSumit Saxena switch (reply_desc_type) { 44942d1d418eSSumit Saxena case MPI3_REPLY_DESCRIPT_FLAGS_TYPE_STATUS: 44952d1d418eSSumit Saxena status_desc = (Mpi3StatusReplyDescriptor_t *)reply_desc; 44962d1d418eSSumit Saxena host_tag = status_desc->HostTag; 44972d1d418eSSumit Saxena ioc_status = status_desc->IOCStatus; 44982d1d418eSSumit Saxena if (ioc_status & 44992d1d418eSSumit Saxena MPI3_REPLY_DESCRIPT_STATUS_IOCSTATUS_LOGINFOAVAIL) 45002d1d418eSSumit Saxena ioc_loginfo = status_desc->IOCLogInfo; 45012d1d418eSSumit Saxena ioc_status &= MPI3_REPLY_DESCRIPT_STATUS_IOCSTATUS_STATUS_MASK; 45022d1d418eSSumit Saxena break; 45032d1d418eSSumit Saxena case MPI3_REPLY_DESCRIPT_FLAGS_TYPE_ADDRESS_REPLY: 45042d1d418eSSumit Saxena addr_desc = (Mpi3AddressReplyDescriptor_t *)reply_desc; 45052d1d418eSSumit Saxena *reply_dma = addr_desc->ReplyFrameAddress; 45062d1d418eSSumit Saxena scsi_reply = mpi3mr_get_reply_virt_addr(sc, 45072d1d418eSSumit Saxena *reply_dma); 45082d1d418eSSumit Saxena if (scsi_reply == NULL) { 45092d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_ERROR, "scsi_reply is NULL, " 45102d1d418eSSumit Saxena "this shouldn't happen, reply_desc: %p\n", 45112d1d418eSSumit Saxena reply_desc); 45122d1d418eSSumit Saxena goto out; 45132d1d418eSSumit Saxena } 45142d1d418eSSumit Saxena 45152d1d418eSSumit Saxena host_tag = scsi_reply->HostTag; 45162d1d418eSSumit Saxena ioc_status = scsi_reply->IOCStatus; 45172d1d418eSSumit Saxena scsi_status = scsi_reply->SCSIStatus; 45182d1d418eSSumit Saxena scsi_state = scsi_reply->SCSIState; 45192d1d418eSSumit Saxena sense_state = (scsi_state & MPI3_SCSI_STATE_SENSE_MASK); 45202d1d418eSSumit Saxena xfer_count = scsi_reply->TransferCount; 45212d1d418eSSumit Saxena sense_count = scsi_reply->SenseCount; 45222d1d418eSSumit Saxena resp_data = scsi_reply->ResponseData; 45232d1d418eSSumit Saxena sense_buf = mpi3mr_get_sensebuf_virt_addr(sc, 45242d1d418eSSumit Saxena scsi_reply->SenseDataBufferAddress); 45252d1d418eSSumit Saxena if (ioc_status & 45262d1d418eSSumit Saxena MPI3_REPLY_DESCRIPT_STATUS_IOCSTATUS_LOGINFOAVAIL) 45272d1d418eSSumit Saxena ioc_loginfo = scsi_reply->IOCLogInfo; 45282d1d418eSSumit Saxena ioc_status &= MPI3_REPLY_DESCRIPT_STATUS_IOCSTATUS_STATUS_MASK; 45292d1d418eSSumit Saxena if (sense_state == MPI3_SCSI_STATE_SENSE_BUFF_Q_EMPTY) 45302d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_ERROR, "Ran out of sense buffers\n"); 45312d1d418eSSumit Saxena 45322d1d418eSSumit Saxena break; 45332d1d418eSSumit Saxena case MPI3_REPLY_DESCRIPT_FLAGS_TYPE_SUCCESS: 45342d1d418eSSumit Saxena success_desc = (Mpi3SuccessReplyDescriptor_t *)reply_desc; 45352d1d418eSSumit Saxena host_tag = success_desc->HostTag; 45362d1d418eSSumit Saxena 45372d1d418eSSumit Saxena default: 45382d1d418eSSumit Saxena break; 45392d1d418eSSumit Saxena } 45402d1d418eSSumit Saxena 45412d1d418eSSumit Saxena cm = sc->cmd_list[host_tag]; 45422d1d418eSSumit Saxena 45432d1d418eSSumit Saxena if (cm->state == MPI3MR_CMD_STATE_FREE) 45442d1d418eSSumit Saxena goto out; 45452d1d418eSSumit Saxena 45462d1d418eSSumit Saxena cam_sc = sc->cam_sc; 45472d1d418eSSumit Saxena ccb = cm->ccb; 45482d1d418eSSumit Saxena csio = &ccb->csio; 45492d1d418eSSumit Saxena target_id = csio->ccb_h.target_id; 45502d1d418eSSumit Saxena 45512d1d418eSSumit Saxena scsi_cdb = scsiio_cdb_ptr(csio); 45522d1d418eSSumit Saxena 45532d1d418eSSumit Saxena target = mpi3mr_find_target_by_per_id(cam_sc, target_id); 45542d1d418eSSumit Saxena if (sc->iot_enable) { 45552d1d418eSSumit Saxena data_len_blks = csio->dxfer_len >> 9; 45562d1d418eSSumit Saxena 45572d1d418eSSumit Saxena if (target) { 45582d1d418eSSumit Saxena tg = target->throttle_group; 45592d1d418eSSumit Saxena throttle_enabled_dev = 45602d1d418eSSumit Saxena target->io_throttle_enabled; 45612d1d418eSSumit Saxena } 45622d1d418eSSumit Saxena 45632d1d418eSSumit Saxena if ((data_len_blks >= sc->io_throttle_data_length) && 45642d1d418eSSumit Saxena throttle_enabled_dev) { 45652d1d418eSSumit Saxena mpi3mr_atomic_sub(&sc->pend_large_data_sz, data_len_blks); 45662d1d418eSSumit Saxena ioc_pend_data_len = mpi3mr_atomic_read( 45672d1d418eSSumit Saxena &sc->pend_large_data_sz); 45682d1d418eSSumit Saxena if (tg) { 45692d1d418eSSumit Saxena mpi3mr_atomic_sub(&tg->pend_large_data_sz, 45702d1d418eSSumit Saxena data_len_blks); 45712d1d418eSSumit Saxena tg_pend_data_len = mpi3mr_atomic_read(&tg->pend_large_data_sz); 45722d1d418eSSumit Saxena if (ratelimit % 1000) { 45732d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_IOT, 45742d1d418eSSumit Saxena "large vd_io completion persist_id(%d), handle(0x%04x), data_len(%d)," 45752d1d418eSSumit Saxena "ioc_pending(%d), tg_pending(%d), ioc_low(%d), tg_low(%d)\n", 45762d1d418eSSumit Saxena target->per_id, 45772d1d418eSSumit Saxena target->dev_handle, 45782d1d418eSSumit Saxena data_len_blks, ioc_pend_data_len, 45792d1d418eSSumit Saxena tg_pend_data_len, 45802d1d418eSSumit Saxena sc->io_throttle_low, 45812d1d418eSSumit Saxena tg->low); 45822d1d418eSSumit Saxena ratelimit++; 45832d1d418eSSumit Saxena } 45842d1d418eSSumit Saxena if (tg->io_divert && ((ioc_pend_data_len <= 45852d1d418eSSumit Saxena sc->io_throttle_low) && 45862d1d418eSSumit Saxena (tg_pend_data_len <= tg->low))) { 45872d1d418eSSumit Saxena tg->io_divert = 0; 45882d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_IOT, 45892d1d418eSSumit Saxena "VD: Coming out of divert perst_id(%d) tg_id(%d)\n", 45902d1d418eSSumit Saxena target->per_id, tg->id); 45912d1d418eSSumit Saxena mpi3mr_set_io_divert_for_all_vd_in_tg( 45922d1d418eSSumit Saxena sc, tg, 0); 45932d1d418eSSumit Saxena } 45942d1d418eSSumit Saxena } else { 45952d1d418eSSumit Saxena if (ratelimit % 1000) { 45962d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_IOT, 45972d1d418eSSumit Saxena "large pd_io completion persist_id(%d), handle(0x%04x), data_len(%d), ioc_pending(%d), ioc_low(%d)\n", 45982d1d418eSSumit Saxena target->per_id, 45992d1d418eSSumit Saxena target->dev_handle, 46002d1d418eSSumit Saxena data_len_blks, ioc_pend_data_len, 46012d1d418eSSumit Saxena sc->io_throttle_low); 46022d1d418eSSumit Saxena ratelimit++; 46032d1d418eSSumit Saxena } 46042d1d418eSSumit Saxena 46052d1d418eSSumit Saxena if (ioc_pend_data_len <= sc->io_throttle_low) { 46062d1d418eSSumit Saxena target->io_divert = 0; 46072d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_IOT, 46082d1d418eSSumit Saxena "PD: Coming out of divert perst_id(%d)\n", 46092d1d418eSSumit Saxena target->per_id); 46102d1d418eSSumit Saxena } 46112d1d418eSSumit Saxena } 46122d1d418eSSumit Saxena 46132d1d418eSSumit Saxena } else if (target->io_divert) { 46142d1d418eSSumit Saxena ioc_pend_data_len = mpi3mr_atomic_read(&sc->pend_large_data_sz); 46152d1d418eSSumit Saxena if (!tg) { 46162d1d418eSSumit Saxena if (ratelimit % 1000) { 46172d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_IOT, 46182d1d418eSSumit Saxena "pd_io completion persist_id(%d), handle(0x%04x), data_len(%d), ioc_pending(%d), ioc_low(%d)\n", 46192d1d418eSSumit Saxena target->per_id, 46202d1d418eSSumit Saxena target->dev_handle, 46212d1d418eSSumit Saxena data_len_blks, ioc_pend_data_len, 46222d1d418eSSumit Saxena sc->io_throttle_low); 46232d1d418eSSumit Saxena ratelimit++; 46242d1d418eSSumit Saxena } 46252d1d418eSSumit Saxena 46262d1d418eSSumit Saxena if ( ioc_pend_data_len <= sc->io_throttle_low) { 46272d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_IOT, 46282d1d418eSSumit Saxena "PD: Coming out of divert perst_id(%d)\n", 46292d1d418eSSumit Saxena target->per_id); 46302d1d418eSSumit Saxena target->io_divert = 0; 46312d1d418eSSumit Saxena } 46322d1d418eSSumit Saxena 46332d1d418eSSumit Saxena } else if (ioc_pend_data_len <= sc->io_throttle_low) { 46342d1d418eSSumit Saxena tg_pend_data_len = mpi3mr_atomic_read(&tg->pend_large_data_sz); 46352d1d418eSSumit Saxena if (ratelimit % 1000) { 46362d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_IOT, 46372d1d418eSSumit Saxena "vd_io completion persist_id(%d), handle(0x%04x), data_len(%d)," 46382d1d418eSSumit Saxena "ioc_pending(%d), tg_pending(%d), ioc_low(%d), tg_low(%d)\n", 46392d1d418eSSumit Saxena target->per_id, 46402d1d418eSSumit Saxena target->dev_handle, 46412d1d418eSSumit Saxena data_len_blks, ioc_pend_data_len, 46422d1d418eSSumit Saxena tg_pend_data_len, 46432d1d418eSSumit Saxena sc->io_throttle_low, 46442d1d418eSSumit Saxena tg->low); 46452d1d418eSSumit Saxena ratelimit++; 46462d1d418eSSumit Saxena } 46472d1d418eSSumit Saxena if (tg->io_divert && (tg_pend_data_len <= tg->low)) { 46482d1d418eSSumit Saxena tg->io_divert = 0; 46492d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_IOT, 46502d1d418eSSumit Saxena "VD: Coming out of divert perst_id(%d) tg_id(%d)\n", 46512d1d418eSSumit Saxena target->per_id, tg->id); 46522d1d418eSSumit Saxena mpi3mr_set_io_divert_for_all_vd_in_tg( 46532d1d418eSSumit Saxena sc, tg, 0); 46542d1d418eSSumit Saxena } 46552d1d418eSSumit Saxena 46562d1d418eSSumit Saxena } 46572d1d418eSSumit Saxena } 46582d1d418eSSumit Saxena } 46592d1d418eSSumit Saxena 46602d1d418eSSumit Saxena if (success_desc) { 46612d1d418eSSumit Saxena mpi3mr_set_ccbstatus(ccb, CAM_REQ_CMP); 46622d1d418eSSumit Saxena goto out_success; 46632d1d418eSSumit Saxena } 46642d1d418eSSumit Saxena 46652d1d418eSSumit Saxena if (ioc_status == MPI3_IOCSTATUS_SCSI_DATA_UNDERRUN 46662d1d418eSSumit Saxena && xfer_count == 0 && (scsi_status == MPI3_SCSI_STATUS_BUSY || 46672d1d418eSSumit Saxena scsi_status == MPI3_SCSI_STATUS_RESERVATION_CONFLICT || 46682d1d418eSSumit Saxena scsi_status == MPI3_SCSI_STATUS_TASK_SET_FULL)) 46692d1d418eSSumit Saxena ioc_status = MPI3_IOCSTATUS_SUCCESS; 46702d1d418eSSumit Saxena 46712d1d418eSSumit Saxena if ((sense_state == MPI3_SCSI_STATE_SENSE_VALID) && sense_count 46722d1d418eSSumit Saxena && sense_buf) { 46732d1d418eSSumit Saxena int sense_len, returned_sense_len; 46742d1d418eSSumit Saxena 46752d1d418eSSumit Saxena returned_sense_len = min(le32toh(sense_count), 46762d1d418eSSumit Saxena sizeof(struct scsi_sense_data)); 46772d1d418eSSumit Saxena if (returned_sense_len < csio->sense_len) 46782d1d418eSSumit Saxena csio->sense_resid = csio->sense_len - 46792d1d418eSSumit Saxena returned_sense_len; 46802d1d418eSSumit Saxena else 46812d1d418eSSumit Saxena csio->sense_resid = 0; 46822d1d418eSSumit Saxena 46832d1d418eSSumit Saxena sense_len = min(returned_sense_len, 46842d1d418eSSumit Saxena csio->sense_len - csio->sense_resid); 46852d1d418eSSumit Saxena bzero(&csio->sense_data, sizeof(csio->sense_data)); 46862d1d418eSSumit Saxena bcopy(sense_buf, &csio->sense_data, sense_len); 46872d1d418eSSumit Saxena ccb->ccb_h.status |= CAM_AUTOSNS_VALID; 46882d1d418eSSumit Saxena } 46892d1d418eSSumit Saxena 46902d1d418eSSumit Saxena switch (ioc_status) { 46912d1d418eSSumit Saxena case MPI3_IOCSTATUS_BUSY: 46922d1d418eSSumit Saxena case MPI3_IOCSTATUS_INSUFFICIENT_RESOURCES: 46932d1d418eSSumit Saxena mpi3mr_set_ccbstatus(ccb, CAM_REQUEUE_REQ); 46942d1d418eSSumit Saxena break; 46952d1d418eSSumit Saxena case MPI3_IOCSTATUS_SCSI_DEVICE_NOT_THERE: 46962d1d418eSSumit Saxena /* 46972d1d418eSSumit Saxena * If devinfo is 0 this will be a volume. In that case don't 46982d1d418eSSumit Saxena * tell CAM that the volume is not there. We want volumes to 46992d1d418eSSumit Saxena * be enumerated until they are deleted/removed, not just 47002d1d418eSSumit Saxena * failed. 47012d1d418eSSumit Saxena */ 47022d1d418eSSumit Saxena if (cm->targ->devinfo == 0) 47032d1d418eSSumit Saxena mpi3mr_set_ccbstatus(ccb, CAM_REQ_CMP); 47042d1d418eSSumit Saxena else 47052d1d418eSSumit Saxena mpi3mr_set_ccbstatus(ccb, CAM_DEV_NOT_THERE); 47062d1d418eSSumit Saxena break; 47072d1d418eSSumit Saxena case MPI3_IOCSTATUS_SCSI_TASK_TERMINATED: 47082d1d418eSSumit Saxena case MPI3_IOCSTATUS_SCSI_IOC_TERMINATED: 47092d1d418eSSumit Saxena case MPI3_IOCSTATUS_SCSI_EXT_TERMINATED: 47102d1d418eSSumit Saxena mpi3mr_set_ccbstatus(ccb, CAM_SCSI_BUSY); 47112d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_TRACE, 47122d1d418eSSumit Saxena "func: %s line:%d tgt %u Hosttag %u loginfo %x\n", 47132d1d418eSSumit Saxena __func__, __LINE__, 47142d1d418eSSumit Saxena target_id, cm->hosttag, 47152d1d418eSSumit Saxena le32toh(scsi_reply->IOCLogInfo)); 47162d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_TRACE, 47172d1d418eSSumit Saxena "SCSIStatus %x SCSIState %x xfercount %u\n", 47182d1d418eSSumit Saxena scsi_reply->SCSIStatus, scsi_reply->SCSIState, 47192d1d418eSSumit Saxena le32toh(xfer_count)); 47202d1d418eSSumit Saxena break; 47212d1d418eSSumit Saxena case MPI3_IOCSTATUS_SCSI_DATA_OVERRUN: 47222d1d418eSSumit Saxena /* resid is ignored for this condition */ 47232d1d418eSSumit Saxena csio->resid = 0; 47242d1d418eSSumit Saxena mpi3mr_set_ccbstatus(ccb, CAM_DATA_RUN_ERR); 47252d1d418eSSumit Saxena break; 47262d1d418eSSumit Saxena case MPI3_IOCSTATUS_SCSI_DATA_UNDERRUN: 47272d1d418eSSumit Saxena csio->resid = cm->length - le32toh(xfer_count); 47282d1d418eSSumit Saxena case MPI3_IOCSTATUS_SCSI_RECOVERED_ERROR: 47292d1d418eSSumit Saxena case MPI3_IOCSTATUS_SUCCESS: 47302d1d418eSSumit Saxena if ((scsi_reply->IOCStatus & MPI3_REPLY_DESCRIPT_STATUS_IOCSTATUS_STATUS_MASK) == 47312d1d418eSSumit Saxena MPI3_IOCSTATUS_SCSI_RECOVERED_ERROR) 47322d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_XINFO, "func: %s line: %d recovered error\n", __func__, __LINE__); 47332d1d418eSSumit Saxena 47342d1d418eSSumit Saxena /* Completion failed at the transport level. */ 47352d1d418eSSumit Saxena if (scsi_reply->SCSIState & (MPI3_SCSI_STATE_NO_SCSI_STATUS | 47362d1d418eSSumit Saxena MPI3_SCSI_STATE_TERMINATED)) { 47372d1d418eSSumit Saxena mpi3mr_set_ccbstatus(ccb, CAM_REQ_CMP_ERR); 47382d1d418eSSumit Saxena break; 47392d1d418eSSumit Saxena } 47402d1d418eSSumit Saxena 47412d1d418eSSumit Saxena /* In a modern packetized environment, an autosense failure 47422d1d418eSSumit Saxena * implies that there's not much else that can be done to 47432d1d418eSSumit Saxena * recover the command. 47442d1d418eSSumit Saxena */ 47452d1d418eSSumit Saxena if (scsi_reply->SCSIState & MPI3_SCSI_STATE_SENSE_VALID) { 47462d1d418eSSumit Saxena mpi3mr_set_ccbstatus(ccb, CAM_AUTOSENSE_FAIL); 47472d1d418eSSumit Saxena break; 47482d1d418eSSumit Saxena } 47492d1d418eSSumit Saxena 47502d1d418eSSumit Saxena /* 47512d1d418eSSumit Saxena * Intentionally override the normal SCSI status reporting 47522d1d418eSSumit Saxena * for these two cases. These are likely to happen in a 47532d1d418eSSumit Saxena * multi-initiator environment, and we want to make sure that 47542d1d418eSSumit Saxena * CAM retries these commands rather than fail them. 47552d1d418eSSumit Saxena */ 47562d1d418eSSumit Saxena if ((scsi_reply->SCSIStatus == MPI3_SCSI_STATUS_COMMAND_TERMINATED) || 47572d1d418eSSumit Saxena (scsi_reply->SCSIStatus == MPI3_SCSI_STATUS_TASK_ABORTED)) { 47582d1d418eSSumit Saxena mpi3mr_set_ccbstatus(ccb, CAM_REQ_ABORTED); 47592d1d418eSSumit Saxena break; 47602d1d418eSSumit Saxena } 47612d1d418eSSumit Saxena 47622d1d418eSSumit Saxena /* Handle normal status and sense */ 47632d1d418eSSumit Saxena csio->scsi_status = scsi_reply->SCSIStatus; 47642d1d418eSSumit Saxena if (scsi_reply->SCSIStatus == MPI3_SCSI_STATUS_GOOD) 47652d1d418eSSumit Saxena mpi3mr_set_ccbstatus(ccb, CAM_REQ_CMP); 47662d1d418eSSumit Saxena else 47672d1d418eSSumit Saxena mpi3mr_set_ccbstatus(ccb, CAM_SCSI_STATUS_ERROR); 47682d1d418eSSumit Saxena 47692d1d418eSSumit Saxena if (scsi_reply->SCSIState & MPI3_SCSI_STATE_SENSE_VALID) { 47702d1d418eSSumit Saxena int sense_len, returned_sense_len; 47712d1d418eSSumit Saxena 47722d1d418eSSumit Saxena returned_sense_len = min(le32toh(scsi_reply->SenseCount), 47732d1d418eSSumit Saxena sizeof(struct scsi_sense_data)); 47742d1d418eSSumit Saxena if (returned_sense_len < csio->sense_len) 47752d1d418eSSumit Saxena csio->sense_resid = csio->sense_len - 47762d1d418eSSumit Saxena returned_sense_len; 47772d1d418eSSumit Saxena else 47782d1d418eSSumit Saxena csio->sense_resid = 0; 47792d1d418eSSumit Saxena 47802d1d418eSSumit Saxena sense_len = min(returned_sense_len, 47812d1d418eSSumit Saxena csio->sense_len - csio->sense_resid); 47822d1d418eSSumit Saxena bzero(&csio->sense_data, sizeof(csio->sense_data)); 47832d1d418eSSumit Saxena bcopy(cm->sense, &csio->sense_data, sense_len); 47842d1d418eSSumit Saxena ccb->ccb_h.status |= CAM_AUTOSNS_VALID; 47852d1d418eSSumit Saxena } 47862d1d418eSSumit Saxena 47872d1d418eSSumit Saxena break; 47882d1d418eSSumit Saxena case MPI3_IOCSTATUS_INVALID_SGL: 47892d1d418eSSumit Saxena mpi3mr_set_ccbstatus(ccb, CAM_UNREC_HBA_ERROR); 47902d1d418eSSumit Saxena break; 47912d1d418eSSumit Saxena case MPI3_IOCSTATUS_EEDP_GUARD_ERROR: 47922d1d418eSSumit Saxena case MPI3_IOCSTATUS_EEDP_REF_TAG_ERROR: 47932d1d418eSSumit Saxena case MPI3_IOCSTATUS_EEDP_APP_TAG_ERROR: 47942d1d418eSSumit Saxena case MPI3_IOCSTATUS_SCSI_PROTOCOL_ERROR: 47952d1d418eSSumit Saxena case MPI3_IOCSTATUS_INVALID_FUNCTION: 47962d1d418eSSumit Saxena case MPI3_IOCSTATUS_INTERNAL_ERROR: 47972d1d418eSSumit Saxena case MPI3_IOCSTATUS_INVALID_FIELD: 47982d1d418eSSumit Saxena case MPI3_IOCSTATUS_INVALID_STATE: 47992d1d418eSSumit Saxena case MPI3_IOCSTATUS_SCSI_IO_DATA_ERROR: 48002d1d418eSSumit Saxena case MPI3_IOCSTATUS_SCSI_TASK_MGMT_FAILED: 48012d1d418eSSumit Saxena case MPI3_IOCSTATUS_INSUFFICIENT_POWER: 48022d1d418eSSumit Saxena case MPI3_IOCSTATUS_SCSI_RESIDUAL_MISMATCH: 48032d1d418eSSumit Saxena default: 48042d1d418eSSumit Saxena csio->resid = cm->length; 48052d1d418eSSumit Saxena mpi3mr_set_ccbstatus(ccb, CAM_REQ_CMP_ERR); 48062d1d418eSSumit Saxena break; 48072d1d418eSSumit Saxena } 48082d1d418eSSumit Saxena 48092d1d418eSSumit Saxena out_success: 48102d1d418eSSumit Saxena if (mpi3mr_get_ccbstatus(ccb) != CAM_REQ_CMP) { 48112d1d418eSSumit Saxena ccb->ccb_h.status |= CAM_DEV_QFRZN; 48122d1d418eSSumit Saxena xpt_freeze_devq(ccb->ccb_h.path, /*count*/ 1); 48132d1d418eSSumit Saxena } 48142d1d418eSSumit Saxena 48152d1d418eSSumit Saxena mpi3mr_atomic_dec(&cm->targ->outstanding); 48162d1d418eSSumit Saxena mpi3mr_cmd_done(sc, cm); 48172d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_TRACE, "Completion IO path :" 48182d1d418eSSumit Saxena " cdb[0]: %x targetid: 0x%x SMID: %x ioc_status: 0x%x ioc_loginfo: 0x%x scsi_status: 0x%x " 48192d1d418eSSumit Saxena "scsi_state: 0x%x response_data: 0x%x\n", scsi_cdb[0], target_id, host_tag, 48202d1d418eSSumit Saxena ioc_status, ioc_loginfo, scsi_status, scsi_state, resp_data); 48212d1d418eSSumit Saxena mpi3mr_atomic_dec(&sc->fw_outstanding); 48222d1d418eSSumit Saxena out: 48232d1d418eSSumit Saxena 48242d1d418eSSumit Saxena if (sense_buf) 48252d1d418eSSumit Saxena mpi3mr_repost_sense_buf(sc, 48262d1d418eSSumit Saxena scsi_reply->SenseDataBufferAddress); 48272d1d418eSSumit Saxena return; 48282d1d418eSSumit Saxena } 48292d1d418eSSumit Saxena 48302d1d418eSSumit Saxena /* 48312d1d418eSSumit Saxena * mpi3mr_complete_io_cmd: ISR routine for IO commands 48322d1d418eSSumit Saxena * @sc: Adapter's soft instance 48332d1d418eSSumit Saxena * @irq_ctx: Driver's internal per IRQ structure 48342d1d418eSSumit Saxena * 48352d1d418eSSumit Saxena * This function processes IO command completions. 48362d1d418eSSumit Saxena */ 48372d1d418eSSumit Saxena int mpi3mr_complete_io_cmd(struct mpi3mr_softc *sc, 48382d1d418eSSumit Saxena struct mpi3mr_irq_context *irq_ctx) 48392d1d418eSSumit Saxena { 48402d1d418eSSumit Saxena struct mpi3mr_op_reply_queue *op_reply_q = irq_ctx->op_reply_q; 48412d1d418eSSumit Saxena U32 exp_phase = op_reply_q->ephase; 48422d1d418eSSumit Saxena U32 reply_ci = op_reply_q->ci; 48432d1d418eSSumit Saxena U32 num_op_replies = 0; 48442d1d418eSSumit Saxena U64 reply_dma = 0; 48452d1d418eSSumit Saxena Mpi3DefaultReplyDescriptor_t *reply_desc; 4846*eb7a4b35SChandrakanth patil U16 req_qid = 0, threshold_comps = 0; 48472d1d418eSSumit Saxena 48482d1d418eSSumit Saxena mtx_lock_spin(&op_reply_q->q_lock); 48492d1d418eSSumit Saxena if (op_reply_q->in_use == false) { 48502d1d418eSSumit Saxena op_reply_q->in_use = true; 48512d1d418eSSumit Saxena mtx_unlock_spin(&op_reply_q->q_lock); 48522d1d418eSSumit Saxena } else { 48532d1d418eSSumit Saxena mtx_unlock_spin(&op_reply_q->q_lock); 48542d1d418eSSumit Saxena return 0; 48552d1d418eSSumit Saxena } 48562d1d418eSSumit Saxena 48572d1d418eSSumit Saxena reply_desc = (Mpi3DefaultReplyDescriptor_t *)op_reply_q->q_base + reply_ci; 48582d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_TRACE, "[QID:%d]:reply_desc: (%pa) reply_ci: %x" 48592d1d418eSSumit Saxena " reply_desc->ReplyFlags: 0x%x\n" 48602d1d418eSSumit Saxena "reply_q_base_phys: %#016jx reply_q_base: (%pa) exp_phase: %x\n", 48612d1d418eSSumit Saxena op_reply_q->qid, reply_desc, reply_ci, reply_desc->ReplyFlags, op_reply_q->q_base_phys, 48622d1d418eSSumit Saxena op_reply_q->q_base, exp_phase); 48632d1d418eSSumit Saxena 48642d1d418eSSumit Saxena if (((reply_desc->ReplyFlags & 48652d1d418eSSumit Saxena MPI3_REPLY_DESCRIPT_FLAGS_PHASE_MASK) != exp_phase) || !op_reply_q->qid) { 48662d1d418eSSumit Saxena mtx_lock_spin(&op_reply_q->q_lock); 48672d1d418eSSumit Saxena op_reply_q->in_use = false; 48682d1d418eSSumit Saxena mtx_unlock_spin(&op_reply_q->q_lock); 48692d1d418eSSumit Saxena return 0; 48702d1d418eSSumit Saxena } 48712d1d418eSSumit Saxena 48722d1d418eSSumit Saxena do { 48732d1d418eSSumit Saxena req_qid = reply_desc->RequestQueueID; 48742d1d418eSSumit Saxena sc->op_req_q[req_qid - 1].ci = 48752d1d418eSSumit Saxena reply_desc->RequestQueueCI; 48762d1d418eSSumit Saxena 48772d1d418eSSumit Saxena mpi3mr_process_op_reply_desc(sc, reply_desc, &reply_dma); 48782d1d418eSSumit Saxena mpi3mr_atomic_dec(&op_reply_q->pend_ios); 48792d1d418eSSumit Saxena if (reply_dma) 48802d1d418eSSumit Saxena mpi3mr_repost_reply_buf(sc, reply_dma); 48812d1d418eSSumit Saxena num_op_replies++; 48822d1d418eSSumit Saxena if (++reply_ci == op_reply_q->num_replies) { 48832d1d418eSSumit Saxena reply_ci = 0; 48842d1d418eSSumit Saxena exp_phase ^= 1; 48852d1d418eSSumit Saxena } 48862d1d418eSSumit Saxena reply_desc = 48872d1d418eSSumit Saxena (Mpi3DefaultReplyDescriptor_t *)op_reply_q->q_base + reply_ci; 48882d1d418eSSumit Saxena if ((reply_desc->ReplyFlags & 48892d1d418eSSumit Saxena MPI3_REPLY_DESCRIPT_FLAGS_PHASE_MASK) != exp_phase) 48902d1d418eSSumit Saxena break; 4891*eb7a4b35SChandrakanth patil 4892*eb7a4b35SChandrakanth patil if (++threshold_comps == MPI3MR_THRESHOLD_REPLY_COUNT) { 4893*eb7a4b35SChandrakanth patil mpi3mr_regwrite(sc, MPI3_SYSIF_OPER_REPLY_Q_N_CI_OFFSET(op_reply_q->qid), reply_ci); 4894*eb7a4b35SChandrakanth patil threshold_comps = 0; 4895*eb7a4b35SChandrakanth patil } 4896*eb7a4b35SChandrakanth patil 48972d1d418eSSumit Saxena } while (1); 48982d1d418eSSumit Saxena 48992d1d418eSSumit Saxena 49002d1d418eSSumit Saxena mpi3mr_regwrite(sc, MPI3_SYSIF_OPER_REPLY_Q_N_CI_OFFSET(op_reply_q->qid), reply_ci); 49012d1d418eSSumit Saxena op_reply_q->ci = reply_ci; 49022d1d418eSSumit Saxena op_reply_q->ephase = exp_phase; 49032d1d418eSSumit Saxena mtx_lock_spin(&op_reply_q->q_lock); 49042d1d418eSSumit Saxena op_reply_q->in_use = false; 49052d1d418eSSumit Saxena mtx_unlock_spin(&op_reply_q->q_lock); 49062d1d418eSSumit Saxena return num_op_replies; 49072d1d418eSSumit Saxena } 49082d1d418eSSumit Saxena 49092d1d418eSSumit Saxena /* 49102d1d418eSSumit Saxena * mpi3mr_isr: Primary ISR function 49112d1d418eSSumit Saxena * privdata: Driver's internal per IRQ structure 49122d1d418eSSumit Saxena * 49132d1d418eSSumit Saxena * This is driver's primary ISR function which is being called whenever any admin/IO 49142d1d418eSSumit Saxena * command completion. 49152d1d418eSSumit Saxena */ 49162d1d418eSSumit Saxena void mpi3mr_isr(void *privdata) 49172d1d418eSSumit Saxena { 49182d1d418eSSumit Saxena struct mpi3mr_irq_context *irq_ctx = (struct mpi3mr_irq_context *)privdata; 49192d1d418eSSumit Saxena struct mpi3mr_softc *sc = irq_ctx->sc; 49202d1d418eSSumit Saxena U16 msi_idx; 49212d1d418eSSumit Saxena 49222d1d418eSSumit Saxena if (!irq_ctx) 49232d1d418eSSumit Saxena return; 49242d1d418eSSumit Saxena 49252d1d418eSSumit Saxena msi_idx = irq_ctx->msix_index; 49262d1d418eSSumit Saxena 49272d1d418eSSumit Saxena if (!sc->intr_enabled) 49282d1d418eSSumit Saxena return; 49292d1d418eSSumit Saxena 49302d1d418eSSumit Saxena if (!msi_idx) 49312d1d418eSSumit Saxena mpi3mr_complete_admin_cmd(sc); 49322d1d418eSSumit Saxena 49332d1d418eSSumit Saxena if (irq_ctx->op_reply_q && irq_ctx->op_reply_q->qid) { 49342d1d418eSSumit Saxena mpi3mr_complete_io_cmd(sc, irq_ctx); 49352d1d418eSSumit Saxena } 49362d1d418eSSumit Saxena } 49372d1d418eSSumit Saxena 49382d1d418eSSumit Saxena /* 49392d1d418eSSumit Saxena * mpi3mr_alloc_requests - Allocates host commands 49402d1d418eSSumit Saxena * @sc: Adapter reference 49412d1d418eSSumit Saxena * 49422d1d418eSSumit Saxena * This function allocates controller supported host commands 49432d1d418eSSumit Saxena * 49442d1d418eSSumit Saxena * Return: 0 on success and proper error codes on failure 49452d1d418eSSumit Saxena */ 49462d1d418eSSumit Saxena int 49472d1d418eSSumit Saxena mpi3mr_alloc_requests(struct mpi3mr_softc *sc) 49482d1d418eSSumit Saxena { 49492d1d418eSSumit Saxena struct mpi3mr_cmd *cmd; 49502d1d418eSSumit Saxena int i, j, nsegs, ret; 49512d1d418eSSumit Saxena 49522d1d418eSSumit Saxena nsegs = MPI3MR_SG_DEPTH; 49532d1d418eSSumit Saxena ret = bus_dma_tag_create( sc->mpi3mr_parent_dmat, /* parent */ 49542d1d418eSSumit Saxena 1, 0, /* algnmnt, boundary */ 4955ee7c431cSWarner Losh sc->dma_loaddr, /* lowaddr */ 49561ec7c672SWarner Losh BUS_SPACE_MAXADDR, /* highaddr */ 49572d1d418eSSumit Saxena NULL, NULL, /* filter, filterarg */ 49584e6d128bSAlexander Motin BUS_SPACE_MAXSIZE, /* maxsize */ 49592d1d418eSSumit Saxena nsegs, /* nsegments */ 49604e6d128bSAlexander Motin BUS_SPACE_MAXSIZE_32BIT,/* maxsegsize */ 49612d1d418eSSumit Saxena BUS_DMA_ALLOCNOW, /* flags */ 49622d1d418eSSumit Saxena busdma_lock_mutex, /* lockfunc */ 49632d1d418eSSumit Saxena &sc->io_lock, /* lockarg */ 49642d1d418eSSumit Saxena &sc->buffer_dmat); 49652d1d418eSSumit Saxena if (ret) { 49662d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_ERROR, "Cannot allocate buffer DMA tag ret: %d\n", ret); 49672d1d418eSSumit Saxena return (ENOMEM); 49682d1d418eSSumit Saxena } 49692d1d418eSSumit Saxena 49702d1d418eSSumit Saxena /* 49712d1d418eSSumit Saxena * sc->cmd_list is an array of struct mpi3mr_cmd pointers. 49722d1d418eSSumit Saxena * Allocate the dynamic array first and then allocate individual 49732d1d418eSSumit Saxena * commands. 49742d1d418eSSumit Saxena */ 49752d1d418eSSumit Saxena sc->cmd_list = malloc(sizeof(struct mpi3mr_cmd *) * sc->max_host_ios, 49762d1d418eSSumit Saxena M_MPI3MR, M_NOWAIT | M_ZERO); 49772d1d418eSSumit Saxena 49782d1d418eSSumit Saxena if (!sc->cmd_list) { 49792d1d418eSSumit Saxena device_printf(sc->mpi3mr_dev, "Cannot alloc memory for mpt_cmd_list.\n"); 49802d1d418eSSumit Saxena return (ENOMEM); 49812d1d418eSSumit Saxena } 49822d1d418eSSumit Saxena 49832d1d418eSSumit Saxena for (i = 0; i < sc->max_host_ios; i++) { 49842d1d418eSSumit Saxena sc->cmd_list[i] = malloc(sizeof(struct mpi3mr_cmd), 49852d1d418eSSumit Saxena M_MPI3MR, M_NOWAIT | M_ZERO); 49862d1d418eSSumit Saxena if (!sc->cmd_list[i]) { 49872d1d418eSSumit Saxena for (j = 0; j < i; j++) 49882d1d418eSSumit Saxena free(sc->cmd_list[j], M_MPI3MR); 49892d1d418eSSumit Saxena free(sc->cmd_list, M_MPI3MR); 49902d1d418eSSumit Saxena sc->cmd_list = NULL; 49912d1d418eSSumit Saxena return (ENOMEM); 49922d1d418eSSumit Saxena } 49932d1d418eSSumit Saxena } 49942d1d418eSSumit Saxena 49952d1d418eSSumit Saxena for (i = 1; i < sc->max_host_ios; i++) { 49962d1d418eSSumit Saxena cmd = sc->cmd_list[i]; 49972d1d418eSSumit Saxena cmd->hosttag = i; 49982d1d418eSSumit Saxena cmd->sc = sc; 49992d1d418eSSumit Saxena cmd->state = MPI3MR_CMD_STATE_BUSY; 50002d1d418eSSumit Saxena callout_init_mtx(&cmd->callout, &sc->mpi3mr_mtx, 0); 50012d1d418eSSumit Saxena cmd->ccb = NULL; 50022d1d418eSSumit Saxena TAILQ_INSERT_TAIL(&(sc->cmd_list_head), cmd, next); 50032d1d418eSSumit Saxena if (bus_dmamap_create(sc->buffer_dmat, 0, &cmd->dmamap)) 50042d1d418eSSumit Saxena return ENOMEM; 50052d1d418eSSumit Saxena } 50062d1d418eSSumit Saxena return (0); 50072d1d418eSSumit Saxena } 50082d1d418eSSumit Saxena 50092d1d418eSSumit Saxena /* 50102d1d418eSSumit Saxena * mpi3mr_get_command: Get a coomand structure from free command pool 50112d1d418eSSumit Saxena * @sc: Adapter soft instance 50122d1d418eSSumit Saxena * Return: MPT command reference 50132d1d418eSSumit Saxena * 50142d1d418eSSumit Saxena * This function returns an MPT command to the caller. 50152d1d418eSSumit Saxena */ 50162d1d418eSSumit Saxena struct mpi3mr_cmd * 50172d1d418eSSumit Saxena mpi3mr_get_command(struct mpi3mr_softc *sc) 50182d1d418eSSumit Saxena { 50192d1d418eSSumit Saxena struct mpi3mr_cmd *cmd = NULL; 50202d1d418eSSumit Saxena 50212d1d418eSSumit Saxena mtx_lock(&sc->cmd_pool_lock); 50222d1d418eSSumit Saxena if (!TAILQ_EMPTY(&sc->cmd_list_head)) { 50232d1d418eSSumit Saxena cmd = TAILQ_FIRST(&sc->cmd_list_head); 50242d1d418eSSumit Saxena TAILQ_REMOVE(&sc->cmd_list_head, cmd, next); 50252d1d418eSSumit Saxena } else { 50262d1d418eSSumit Saxena goto out; 50272d1d418eSSumit Saxena } 50282d1d418eSSumit Saxena 50292d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_TRACE, "Get command SMID: 0x%x\n", cmd->hosttag); 50302d1d418eSSumit Saxena 50312d1d418eSSumit Saxena memset((uint8_t *)&cmd->io_request, 0, MPI3MR_AREQ_FRAME_SZ); 50322d1d418eSSumit Saxena cmd->data_dir = 0; 50332d1d418eSSumit Saxena cmd->ccb = NULL; 50342d1d418eSSumit Saxena cmd->targ = NULL; 50352d1d418eSSumit Saxena cmd->state = MPI3MR_CMD_STATE_BUSY; 50362d1d418eSSumit Saxena cmd->data = NULL; 50372d1d418eSSumit Saxena cmd->length = 0; 50382d1d418eSSumit Saxena out: 50392d1d418eSSumit Saxena mtx_unlock(&sc->cmd_pool_lock); 50402d1d418eSSumit Saxena return cmd; 50412d1d418eSSumit Saxena } 50422d1d418eSSumit Saxena 50432d1d418eSSumit Saxena /* 50442d1d418eSSumit Saxena * mpi3mr_release_command: Return a cmd to free command pool 50452d1d418eSSumit Saxena * input: Command packet for return to free command pool 50462d1d418eSSumit Saxena * 50472d1d418eSSumit Saxena * This function returns an MPT command to the free command list. 50482d1d418eSSumit Saxena */ 50492d1d418eSSumit Saxena void 50502d1d418eSSumit Saxena mpi3mr_release_command(struct mpi3mr_cmd *cmd) 50512d1d418eSSumit Saxena { 50522d1d418eSSumit Saxena struct mpi3mr_softc *sc = cmd->sc; 50532d1d418eSSumit Saxena 50542d1d418eSSumit Saxena mtx_lock(&sc->cmd_pool_lock); 50552d1d418eSSumit Saxena TAILQ_INSERT_HEAD(&(sc->cmd_list_head), cmd, next); 50562d1d418eSSumit Saxena cmd->state = MPI3MR_CMD_STATE_FREE; 50572d1d418eSSumit Saxena cmd->req_qidx = 0; 50582d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_TRACE, "Release command SMID: 0x%x\n", cmd->hosttag); 50592d1d418eSSumit Saxena mtx_unlock(&sc->cmd_pool_lock); 50602d1d418eSSumit Saxena 50612d1d418eSSumit Saxena return; 50622d1d418eSSumit Saxena } 50632d1d418eSSumit Saxena 50642d1d418eSSumit Saxena /** 50652d1d418eSSumit Saxena * mpi3mr_free_ioctl_dma_memory - free memory for ioctl dma 50662d1d418eSSumit Saxena * @sc: Adapter instance reference 50672d1d418eSSumit Saxena * 50682d1d418eSSumit Saxena * Free the DMA memory allocated for IOCTL handling purpose. 50692d1d418eSSumit Saxena * 50702d1d418eSSumit Saxena * Return: None 50712d1d418eSSumit Saxena */ 50722d1d418eSSumit Saxena static void mpi3mr_free_ioctl_dma_memory(struct mpi3mr_softc *sc) 50732d1d418eSSumit Saxena { 50742d1d418eSSumit Saxena U16 i; 50752d1d418eSSumit Saxena struct dma_memory_desc *mem_desc; 50762d1d418eSSumit Saxena 50772d1d418eSSumit Saxena for (i=0; i<MPI3MR_NUM_IOCTL_SGE; i++) { 50782d1d418eSSumit Saxena mem_desc = &sc->ioctl_sge[i]; 50792d1d418eSSumit Saxena if (mem_desc->addr && mem_desc->dma_addr) { 50802d1d418eSSumit Saxena bus_dmamap_unload(mem_desc->tag, mem_desc->dmamap); 50812d1d418eSSumit Saxena bus_dmamem_free(mem_desc->tag, mem_desc->addr, mem_desc->dmamap); 50822d1d418eSSumit Saxena mem_desc->addr = NULL; 50832d1d418eSSumit Saxena if (mem_desc->tag != NULL) 50842d1d418eSSumit Saxena bus_dma_tag_destroy(mem_desc->tag); 50852d1d418eSSumit Saxena } 50862d1d418eSSumit Saxena } 50872d1d418eSSumit Saxena 50882d1d418eSSumit Saxena mem_desc = &sc->ioctl_chain_sge; 50892d1d418eSSumit Saxena if (mem_desc->addr && mem_desc->dma_addr) { 50902d1d418eSSumit Saxena bus_dmamap_unload(mem_desc->tag, mem_desc->dmamap); 50912d1d418eSSumit Saxena bus_dmamem_free(mem_desc->tag, mem_desc->addr, mem_desc->dmamap); 50922d1d418eSSumit Saxena mem_desc->addr = NULL; 50932d1d418eSSumit Saxena if (mem_desc->tag != NULL) 50942d1d418eSSumit Saxena bus_dma_tag_destroy(mem_desc->tag); 50952d1d418eSSumit Saxena } 50962d1d418eSSumit Saxena 50972d1d418eSSumit Saxena mem_desc = &sc->ioctl_resp_sge; 50982d1d418eSSumit Saxena if (mem_desc->addr && mem_desc->dma_addr) { 50992d1d418eSSumit Saxena bus_dmamap_unload(mem_desc->tag, mem_desc->dmamap); 51002d1d418eSSumit Saxena bus_dmamem_free(mem_desc->tag, mem_desc->addr, mem_desc->dmamap); 51012d1d418eSSumit Saxena mem_desc->addr = NULL; 51022d1d418eSSumit Saxena if (mem_desc->tag != NULL) 51032d1d418eSSumit Saxena bus_dma_tag_destroy(mem_desc->tag); 51042d1d418eSSumit Saxena } 51052d1d418eSSumit Saxena 51062d1d418eSSumit Saxena sc->ioctl_sges_allocated = false; 51072d1d418eSSumit Saxena } 51082d1d418eSSumit Saxena 51092d1d418eSSumit Saxena /** 51102d1d418eSSumit Saxena * mpi3mr_alloc_ioctl_dma_memory - Alloc memory for ioctl dma 51112d1d418eSSumit Saxena * @sc: Adapter instance reference 51122d1d418eSSumit Saxena * 51132d1d418eSSumit Saxena * This function allocates dmaable memory required to handle the 51142d1d418eSSumit Saxena * application issued MPI3 IOCTL requests. 51152d1d418eSSumit Saxena * 51162d1d418eSSumit Saxena * Return: None 51172d1d418eSSumit Saxena */ 51182d1d418eSSumit Saxena void mpi3mr_alloc_ioctl_dma_memory(struct mpi3mr_softc *sc) 51192d1d418eSSumit Saxena { 51202d1d418eSSumit Saxena struct dma_memory_desc *mem_desc; 51212d1d418eSSumit Saxena U16 i; 51222d1d418eSSumit Saxena 51232d1d418eSSumit Saxena for (i=0; i<MPI3MR_NUM_IOCTL_SGE; i++) { 51242d1d418eSSumit Saxena mem_desc = &sc->ioctl_sge[i]; 51252d1d418eSSumit Saxena mem_desc->size = MPI3MR_IOCTL_SGE_SIZE; 51262d1d418eSSumit Saxena 51272d1d418eSSumit Saxena if (bus_dma_tag_create(sc->mpi3mr_parent_dmat, /* parent */ 51282d1d418eSSumit Saxena 4, 0, /* algnmnt, boundary */ 5129ee7c431cSWarner Losh sc->dma_loaddr, /* lowaddr */ 51301ec7c672SWarner Losh BUS_SPACE_MAXADDR, /* highaddr */ 51312d1d418eSSumit Saxena NULL, NULL, /* filter, filterarg */ 51322d1d418eSSumit Saxena mem_desc->size, /* maxsize */ 51332d1d418eSSumit Saxena 1, /* nsegments */ 51342d1d418eSSumit Saxena mem_desc->size, /* maxsegsize */ 51352d1d418eSSumit Saxena 0, /* flags */ 51362d1d418eSSumit Saxena NULL, NULL, /* lockfunc, lockarg */ 51372d1d418eSSumit Saxena &mem_desc->tag)) { 51382d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_ERROR, "Cannot allocate request DMA tag\n"); 51392d1d418eSSumit Saxena goto out_failed; 51402d1d418eSSumit Saxena } 51412d1d418eSSumit Saxena 51422d1d418eSSumit Saxena if (bus_dmamem_alloc(mem_desc->tag, (void **)&mem_desc->addr, 51432d1d418eSSumit Saxena BUS_DMA_NOWAIT, &mem_desc->dmamap)) { 5144ee7c431cSWarner Losh mpi3mr_dprint(sc, MPI3MR_ERROR, "%s: Cannot allocate replies memory\n", __func__); 51452d1d418eSSumit Saxena goto out_failed; 51462d1d418eSSumit Saxena } 51472d1d418eSSumit Saxena bzero(mem_desc->addr, mem_desc->size); 51482d1d418eSSumit Saxena bus_dmamap_load(mem_desc->tag, mem_desc->dmamap, mem_desc->addr, mem_desc->size, 514939a3e6a8SAlexander Motin mpi3mr_memaddr_cb, &mem_desc->dma_addr, BUS_DMA_NOWAIT); 51502d1d418eSSumit Saxena 51512d1d418eSSumit Saxena if (!mem_desc->addr) 51522d1d418eSSumit Saxena goto out_failed; 51532d1d418eSSumit Saxena } 51542d1d418eSSumit Saxena 51552d1d418eSSumit Saxena mem_desc = &sc->ioctl_chain_sge; 51562d1d418eSSumit Saxena mem_desc->size = MPI3MR_4K_PGSZ; 51572d1d418eSSumit Saxena if (bus_dma_tag_create(sc->mpi3mr_parent_dmat, /* parent */ 51582d1d418eSSumit Saxena 4, 0, /* algnmnt, boundary */ 5159ee7c431cSWarner Losh sc->dma_loaddr, /* lowaddr */ 51601ec7c672SWarner Losh BUS_SPACE_MAXADDR, /* highaddr */ 51612d1d418eSSumit Saxena NULL, NULL, /* filter, filterarg */ 51622d1d418eSSumit Saxena mem_desc->size, /* maxsize */ 51632d1d418eSSumit Saxena 1, /* nsegments */ 51642d1d418eSSumit Saxena mem_desc->size, /* maxsegsize */ 51652d1d418eSSumit Saxena 0, /* flags */ 51662d1d418eSSumit Saxena NULL, NULL, /* lockfunc, lockarg */ 51672d1d418eSSumit Saxena &mem_desc->tag)) { 51682d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_ERROR, "Cannot allocate request DMA tag\n"); 51692d1d418eSSumit Saxena goto out_failed; 51702d1d418eSSumit Saxena } 51712d1d418eSSumit Saxena 51722d1d418eSSumit Saxena if (bus_dmamem_alloc(mem_desc->tag, (void **)&mem_desc->addr, 51732d1d418eSSumit Saxena BUS_DMA_NOWAIT, &mem_desc->dmamap)) { 5174ee7c431cSWarner Losh mpi3mr_dprint(sc, MPI3MR_ERROR, "%s: Cannot allocate replies memory\n", __func__); 51752d1d418eSSumit Saxena goto out_failed; 51762d1d418eSSumit Saxena } 51772d1d418eSSumit Saxena bzero(mem_desc->addr, mem_desc->size); 51782d1d418eSSumit Saxena bus_dmamap_load(mem_desc->tag, mem_desc->dmamap, mem_desc->addr, mem_desc->size, 517939a3e6a8SAlexander Motin mpi3mr_memaddr_cb, &mem_desc->dma_addr, BUS_DMA_NOWAIT); 51802d1d418eSSumit Saxena 51812d1d418eSSumit Saxena if (!mem_desc->addr) 51822d1d418eSSumit Saxena goto out_failed; 51832d1d418eSSumit Saxena 51842d1d418eSSumit Saxena mem_desc = &sc->ioctl_resp_sge; 51852d1d418eSSumit Saxena mem_desc->size = MPI3MR_4K_PGSZ; 51862d1d418eSSumit Saxena if (bus_dma_tag_create(sc->mpi3mr_parent_dmat, /* parent */ 51872d1d418eSSumit Saxena 4, 0, /* algnmnt, boundary */ 5188ee7c431cSWarner Losh sc->dma_loaddr, /* lowaddr */ 51891ec7c672SWarner Losh BUS_SPACE_MAXADDR, /* highaddr */ 51902d1d418eSSumit Saxena NULL, NULL, /* filter, filterarg */ 51912d1d418eSSumit Saxena mem_desc->size, /* maxsize */ 51922d1d418eSSumit Saxena 1, /* nsegments */ 51932d1d418eSSumit Saxena mem_desc->size, /* maxsegsize */ 51942d1d418eSSumit Saxena 0, /* flags */ 51952d1d418eSSumit Saxena NULL, NULL, /* lockfunc, lockarg */ 51962d1d418eSSumit Saxena &mem_desc->tag)) { 51972d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_ERROR, "Cannot allocate request DMA tag\n"); 51982d1d418eSSumit Saxena goto out_failed; 51992d1d418eSSumit Saxena } 52002d1d418eSSumit Saxena 52012d1d418eSSumit Saxena if (bus_dmamem_alloc(mem_desc->tag, (void **)&mem_desc->addr, 52022d1d418eSSumit Saxena BUS_DMA_NOWAIT, &mem_desc->dmamap)) { 52032d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_ERROR, "Cannot allocate replies memory\n"); 52042d1d418eSSumit Saxena goto out_failed; 52052d1d418eSSumit Saxena } 52062d1d418eSSumit Saxena bzero(mem_desc->addr, mem_desc->size); 52072d1d418eSSumit Saxena bus_dmamap_load(mem_desc->tag, mem_desc->dmamap, mem_desc->addr, mem_desc->size, 520839a3e6a8SAlexander Motin mpi3mr_memaddr_cb, &mem_desc->dma_addr, BUS_DMA_NOWAIT); 52092d1d418eSSumit Saxena 52102d1d418eSSumit Saxena if (!mem_desc->addr) 52112d1d418eSSumit Saxena goto out_failed; 52122d1d418eSSumit Saxena 52132d1d418eSSumit Saxena sc->ioctl_sges_allocated = true; 52142d1d418eSSumit Saxena 52152d1d418eSSumit Saxena return; 52162d1d418eSSumit Saxena out_failed: 52172d1d418eSSumit Saxena printf("cannot allocate DMA memory for the mpt commands" 52182d1d418eSSumit Saxena " from the applications, application interface for MPT command is disabled\n"); 52192d1d418eSSumit Saxena mpi3mr_free_ioctl_dma_memory(sc); 52202d1d418eSSumit Saxena } 52212d1d418eSSumit Saxena 52222d1d418eSSumit Saxena void 52232d1d418eSSumit Saxena mpi3mr_destory_mtx(struct mpi3mr_softc *sc) 52242d1d418eSSumit Saxena { 52252d1d418eSSumit Saxena int i; 52262d1d418eSSumit Saxena struct mpi3mr_op_req_queue *op_req_q; 52272d1d418eSSumit Saxena struct mpi3mr_op_reply_queue *op_reply_q; 52282d1d418eSSumit Saxena 52292d1d418eSSumit Saxena if (sc->admin_reply) { 52302d1d418eSSumit Saxena if (mtx_initialized(&sc->admin_reply_lock)) 52312d1d418eSSumit Saxena mtx_destroy(&sc->admin_reply_lock); 52322d1d418eSSumit Saxena } 52332d1d418eSSumit Saxena 52342d1d418eSSumit Saxena if (sc->op_reply_q) { 52352d1d418eSSumit Saxena for(i = 0; i < sc->num_queues; i++) { 52362d1d418eSSumit Saxena op_reply_q = sc->op_reply_q + i; 52372d1d418eSSumit Saxena if (mtx_initialized(&op_reply_q->q_lock)) 52382d1d418eSSumit Saxena mtx_destroy(&op_reply_q->q_lock); 52392d1d418eSSumit Saxena } 52402d1d418eSSumit Saxena } 52412d1d418eSSumit Saxena 52422d1d418eSSumit Saxena if (sc->op_req_q) { 52432d1d418eSSumit Saxena for(i = 0; i < sc->num_queues; i++) { 52442d1d418eSSumit Saxena op_req_q = sc->op_req_q + i; 52452d1d418eSSumit Saxena if (mtx_initialized(&op_req_q->q_lock)) 52462d1d418eSSumit Saxena mtx_destroy(&op_req_q->q_lock); 52472d1d418eSSumit Saxena } 52482d1d418eSSumit Saxena } 52492d1d418eSSumit Saxena 52502d1d418eSSumit Saxena if (mtx_initialized(&sc->init_cmds.completion.lock)) 52512d1d418eSSumit Saxena mtx_destroy(&sc->init_cmds.completion.lock); 52522d1d418eSSumit Saxena 52532d1d418eSSumit Saxena if (mtx_initialized(&sc->ioctl_cmds.completion.lock)) 52542d1d418eSSumit Saxena mtx_destroy(&sc->ioctl_cmds.completion.lock); 52552d1d418eSSumit Saxena 52562d1d418eSSumit Saxena if (mtx_initialized(&sc->host_tm_cmds.completion.lock)) 52572d1d418eSSumit Saxena mtx_destroy(&sc->host_tm_cmds.completion.lock); 52582d1d418eSSumit Saxena 52592d1d418eSSumit Saxena for (i = 0; i < MPI3MR_NUM_DEVRMCMD; i++) { 52602d1d418eSSumit Saxena if (mtx_initialized(&sc->dev_rmhs_cmds[i].completion.lock)) 52612d1d418eSSumit Saxena mtx_destroy(&sc->dev_rmhs_cmds[i].completion.lock); 52622d1d418eSSumit Saxena } 52632d1d418eSSumit Saxena 52642d1d418eSSumit Saxena if (mtx_initialized(&sc->reset_mutex)) 52652d1d418eSSumit Saxena mtx_destroy(&sc->reset_mutex); 52662d1d418eSSumit Saxena 52672d1d418eSSumit Saxena if (mtx_initialized(&sc->target_lock)) 52682d1d418eSSumit Saxena mtx_destroy(&sc->target_lock); 52692d1d418eSSumit Saxena 52702d1d418eSSumit Saxena if (mtx_initialized(&sc->fwevt_lock)) 52712d1d418eSSumit Saxena mtx_destroy(&sc->fwevt_lock); 52722d1d418eSSumit Saxena 52732d1d418eSSumit Saxena if (mtx_initialized(&sc->cmd_pool_lock)) 52742d1d418eSSumit Saxena mtx_destroy(&sc->cmd_pool_lock); 52752d1d418eSSumit Saxena 52762d1d418eSSumit Saxena if (mtx_initialized(&sc->reply_free_q_lock)) 52772d1d418eSSumit Saxena mtx_destroy(&sc->reply_free_q_lock); 52782d1d418eSSumit Saxena 52792d1d418eSSumit Saxena if (mtx_initialized(&sc->sense_buf_q_lock)) 52802d1d418eSSumit Saxena mtx_destroy(&sc->sense_buf_q_lock); 52812d1d418eSSumit Saxena 52822d1d418eSSumit Saxena if (mtx_initialized(&sc->chain_buf_lock)) 52832d1d418eSSumit Saxena mtx_destroy(&sc->chain_buf_lock); 52842d1d418eSSumit Saxena 52852d1d418eSSumit Saxena if (mtx_initialized(&sc->admin_req_lock)) 52862d1d418eSSumit Saxena mtx_destroy(&sc->admin_req_lock); 52872d1d418eSSumit Saxena 52882d1d418eSSumit Saxena if (mtx_initialized(&sc->mpi3mr_mtx)) 52892d1d418eSSumit Saxena mtx_destroy(&sc->mpi3mr_mtx); 52902d1d418eSSumit Saxena } 52912d1d418eSSumit Saxena 52922d1d418eSSumit Saxena /** 52932d1d418eSSumit Saxena * mpi3mr_free_mem - Freeup adapter level data structures 52942d1d418eSSumit Saxena * @sc: Adapter reference 52952d1d418eSSumit Saxena * 52962d1d418eSSumit Saxena * Return: Nothing. 52972d1d418eSSumit Saxena */ 52982d1d418eSSumit Saxena void 52992d1d418eSSumit Saxena mpi3mr_free_mem(struct mpi3mr_softc *sc) 53002d1d418eSSumit Saxena { 53012d1d418eSSumit Saxena int i; 53022d1d418eSSumit Saxena struct mpi3mr_op_req_queue *op_req_q; 53032d1d418eSSumit Saxena struct mpi3mr_op_reply_queue *op_reply_q; 53042d1d418eSSumit Saxena struct mpi3mr_irq_context *irq_ctx; 53052d1d418eSSumit Saxena 53062d1d418eSSumit Saxena if (sc->cmd_list) { 53072d1d418eSSumit Saxena for (i = 0; i < sc->max_host_ios; i++) { 53082d1d418eSSumit Saxena free(sc->cmd_list[i], M_MPI3MR); 53092d1d418eSSumit Saxena } 53102d1d418eSSumit Saxena free(sc->cmd_list, M_MPI3MR); 53112d1d418eSSumit Saxena sc->cmd_list = NULL; 53122d1d418eSSumit Saxena } 53132d1d418eSSumit Saxena 53142d1d418eSSumit Saxena if (sc->pel_seq_number && sc->pel_seq_number_dma) { 53152d1d418eSSumit Saxena bus_dmamap_unload(sc->pel_seq_num_dmatag, sc->pel_seq_num_dmamap); 53162d1d418eSSumit Saxena bus_dmamem_free(sc->pel_seq_num_dmatag, sc->pel_seq_number, sc->pel_seq_num_dmamap); 53172d1d418eSSumit Saxena sc->pel_seq_number = NULL; 53182d1d418eSSumit Saxena if (sc->pel_seq_num_dmatag != NULL) 53192d1d418eSSumit Saxena bus_dma_tag_destroy(sc->pel_seq_num_dmatag); 53202d1d418eSSumit Saxena } 53212d1d418eSSumit Saxena 53222d1d418eSSumit Saxena if (sc->throttle_groups) { 53232d1d418eSSumit Saxena free(sc->throttle_groups, M_MPI3MR); 53242d1d418eSSumit Saxena sc->throttle_groups = NULL; 53252d1d418eSSumit Saxena } 53262d1d418eSSumit Saxena 53272d1d418eSSumit Saxena /* Free up operational queues*/ 53282d1d418eSSumit Saxena if (sc->op_req_q) { 53292d1d418eSSumit Saxena for (i = 0; i < sc->num_queues; i++) { 53302d1d418eSSumit Saxena op_req_q = sc->op_req_q + i; 53312d1d418eSSumit Saxena if (op_req_q->q_base && op_req_q->q_base_phys) { 53322d1d418eSSumit Saxena bus_dmamap_unload(op_req_q->q_base_tag, op_req_q->q_base_dmamap); 53332d1d418eSSumit Saxena bus_dmamem_free(op_req_q->q_base_tag, op_req_q->q_base, op_req_q->q_base_dmamap); 53342d1d418eSSumit Saxena op_req_q->q_base = NULL; 53352d1d418eSSumit Saxena if (op_req_q->q_base_tag != NULL) 53362d1d418eSSumit Saxena bus_dma_tag_destroy(op_req_q->q_base_tag); 53372d1d418eSSumit Saxena } 53382d1d418eSSumit Saxena } 53392d1d418eSSumit Saxena free(sc->op_req_q, M_MPI3MR); 53402d1d418eSSumit Saxena sc->op_req_q = NULL; 53412d1d418eSSumit Saxena } 53422d1d418eSSumit Saxena 53432d1d418eSSumit Saxena if (sc->op_reply_q) { 53442d1d418eSSumit Saxena for (i = 0; i < sc->num_queues; i++) { 53452d1d418eSSumit Saxena op_reply_q = sc->op_reply_q + i; 53462d1d418eSSumit Saxena if (op_reply_q->q_base && op_reply_q->q_base_phys) { 53472d1d418eSSumit Saxena bus_dmamap_unload(op_reply_q->q_base_tag, op_reply_q->q_base_dmamap); 53482d1d418eSSumit Saxena bus_dmamem_free(op_reply_q->q_base_tag, op_reply_q->q_base, op_reply_q->q_base_dmamap); 53492d1d418eSSumit Saxena op_reply_q->q_base = NULL; 53502d1d418eSSumit Saxena if (op_reply_q->q_base_tag != NULL) 53512d1d418eSSumit Saxena bus_dma_tag_destroy(op_reply_q->q_base_tag); 53522d1d418eSSumit Saxena } 53532d1d418eSSumit Saxena } 53542d1d418eSSumit Saxena free(sc->op_reply_q, M_MPI3MR); 53552d1d418eSSumit Saxena sc->op_reply_q = NULL; 53562d1d418eSSumit Saxena } 53572d1d418eSSumit Saxena 53582d1d418eSSumit Saxena /* Free up chain buffers*/ 53592d1d418eSSumit Saxena if (sc->chain_sgl_list) { 53602d1d418eSSumit Saxena for (i = 0; i < sc->chain_buf_count; i++) { 53612d1d418eSSumit Saxena if (sc->chain_sgl_list[i].buf && sc->chain_sgl_list[i].buf_phys) { 53622d1d418eSSumit Saxena bus_dmamap_unload(sc->chain_sgl_list_tag, sc->chain_sgl_list[i].buf_dmamap); 53632d1d418eSSumit Saxena bus_dmamem_free(sc->chain_sgl_list_tag, sc->chain_sgl_list[i].buf, 53642d1d418eSSumit Saxena sc->chain_sgl_list[i].buf_dmamap); 53652d1d418eSSumit Saxena sc->chain_sgl_list[i].buf = NULL; 53662d1d418eSSumit Saxena } 53672d1d418eSSumit Saxena } 53682d1d418eSSumit Saxena if (sc->chain_sgl_list_tag != NULL) 53692d1d418eSSumit Saxena bus_dma_tag_destroy(sc->chain_sgl_list_tag); 53702d1d418eSSumit Saxena free(sc->chain_sgl_list, M_MPI3MR); 53712d1d418eSSumit Saxena sc->chain_sgl_list = NULL; 53722d1d418eSSumit Saxena } 53732d1d418eSSumit Saxena 53742d1d418eSSumit Saxena if (sc->chain_bitmap) { 53752d1d418eSSumit Saxena free(sc->chain_bitmap, M_MPI3MR); 53762d1d418eSSumit Saxena sc->chain_bitmap = NULL; 53772d1d418eSSumit Saxena } 53782d1d418eSSumit Saxena 53792d1d418eSSumit Saxena for (i = 0; i < sc->msix_count; i++) { 53802d1d418eSSumit Saxena irq_ctx = sc->irq_ctx + i; 53812d1d418eSSumit Saxena if (irq_ctx) 53822d1d418eSSumit Saxena irq_ctx->op_reply_q = NULL; 53832d1d418eSSumit Saxena } 53842d1d418eSSumit Saxena 53852d1d418eSSumit Saxena /* Free reply_buf_tag */ 53862d1d418eSSumit Saxena if (sc->reply_buf && sc->reply_buf_phys) { 53872d1d418eSSumit Saxena bus_dmamap_unload(sc->reply_buf_tag, sc->reply_buf_dmamap); 53882d1d418eSSumit Saxena bus_dmamem_free(sc->reply_buf_tag, sc->reply_buf, 53892d1d418eSSumit Saxena sc->reply_buf_dmamap); 53902d1d418eSSumit Saxena sc->reply_buf = NULL; 53912d1d418eSSumit Saxena if (sc->reply_buf_tag != NULL) 53922d1d418eSSumit Saxena bus_dma_tag_destroy(sc->reply_buf_tag); 53932d1d418eSSumit Saxena } 53942d1d418eSSumit Saxena 53952d1d418eSSumit Saxena /* Free reply_free_q_tag */ 53962d1d418eSSumit Saxena if (sc->reply_free_q && sc->reply_free_q_phys) { 53972d1d418eSSumit Saxena bus_dmamap_unload(sc->reply_free_q_tag, sc->reply_free_q_dmamap); 53982d1d418eSSumit Saxena bus_dmamem_free(sc->reply_free_q_tag, sc->reply_free_q, 53992d1d418eSSumit Saxena sc->reply_free_q_dmamap); 54002d1d418eSSumit Saxena sc->reply_free_q = NULL; 54012d1d418eSSumit Saxena if (sc->reply_free_q_tag != NULL) 54022d1d418eSSumit Saxena bus_dma_tag_destroy(sc->reply_free_q_tag); 54032d1d418eSSumit Saxena } 54042d1d418eSSumit Saxena 54052d1d418eSSumit Saxena /* Free sense_buf_tag */ 54062d1d418eSSumit Saxena if (sc->sense_buf && sc->sense_buf_phys) { 54072d1d418eSSumit Saxena bus_dmamap_unload(sc->sense_buf_tag, sc->sense_buf_dmamap); 54082d1d418eSSumit Saxena bus_dmamem_free(sc->sense_buf_tag, sc->sense_buf, 54092d1d418eSSumit Saxena sc->sense_buf_dmamap); 54102d1d418eSSumit Saxena sc->sense_buf = NULL; 54112d1d418eSSumit Saxena if (sc->sense_buf_tag != NULL) 54122d1d418eSSumit Saxena bus_dma_tag_destroy(sc->sense_buf_tag); 54132d1d418eSSumit Saxena } 54142d1d418eSSumit Saxena 54152d1d418eSSumit Saxena /* Free sense_buf_q_tag */ 54162d1d418eSSumit Saxena if (sc->sense_buf_q && sc->sense_buf_q_phys) { 54172d1d418eSSumit Saxena bus_dmamap_unload(sc->sense_buf_q_tag, sc->sense_buf_q_dmamap); 54182d1d418eSSumit Saxena bus_dmamem_free(sc->sense_buf_q_tag, sc->sense_buf_q, 54192d1d418eSSumit Saxena sc->sense_buf_q_dmamap); 54202d1d418eSSumit Saxena sc->sense_buf_q = NULL; 54212d1d418eSSumit Saxena if (sc->sense_buf_q_tag != NULL) 54222d1d418eSSumit Saxena bus_dma_tag_destroy(sc->sense_buf_q_tag); 54232d1d418eSSumit Saxena } 54242d1d418eSSumit Saxena 54252d1d418eSSumit Saxena /* Free up internal(non-IO) commands*/ 54262d1d418eSSumit Saxena if (sc->init_cmds.reply) { 54272d1d418eSSumit Saxena free(sc->init_cmds.reply, M_MPI3MR); 54282d1d418eSSumit Saxena sc->init_cmds.reply = NULL; 54292d1d418eSSumit Saxena } 54302d1d418eSSumit Saxena 54312d1d418eSSumit Saxena if (sc->ioctl_cmds.reply) { 54322d1d418eSSumit Saxena free(sc->ioctl_cmds.reply, M_MPI3MR); 54332d1d418eSSumit Saxena sc->ioctl_cmds.reply = NULL; 54342d1d418eSSumit Saxena } 54352d1d418eSSumit Saxena 54362d1d418eSSumit Saxena if (sc->pel_cmds.reply) { 54372d1d418eSSumit Saxena free(sc->pel_cmds.reply, M_MPI3MR); 54382d1d418eSSumit Saxena sc->pel_cmds.reply = NULL; 54392d1d418eSSumit Saxena } 54402d1d418eSSumit Saxena 54412d1d418eSSumit Saxena if (sc->pel_abort_cmd.reply) { 54422d1d418eSSumit Saxena free(sc->pel_abort_cmd.reply, M_MPI3MR); 54432d1d418eSSumit Saxena sc->pel_abort_cmd.reply = NULL; 54442d1d418eSSumit Saxena } 54452d1d418eSSumit Saxena 54462d1d418eSSumit Saxena if (sc->host_tm_cmds.reply) { 54472d1d418eSSumit Saxena free(sc->host_tm_cmds.reply, M_MPI3MR); 54482d1d418eSSumit Saxena sc->host_tm_cmds.reply = NULL; 54492d1d418eSSumit Saxena } 54502d1d418eSSumit Saxena 54512d1d418eSSumit Saxena if (sc->log_data_buffer) { 54522d1d418eSSumit Saxena free(sc->log_data_buffer, M_MPI3MR); 54532d1d418eSSumit Saxena sc->log_data_buffer = NULL; 54542d1d418eSSumit Saxena } 54552d1d418eSSumit Saxena 54562d1d418eSSumit Saxena for (i = 0; i < MPI3MR_NUM_DEVRMCMD; i++) { 54572d1d418eSSumit Saxena if (sc->dev_rmhs_cmds[i].reply) { 54582d1d418eSSumit Saxena free(sc->dev_rmhs_cmds[i].reply, M_MPI3MR); 54592d1d418eSSumit Saxena sc->dev_rmhs_cmds[i].reply = NULL; 54602d1d418eSSumit Saxena } 54612d1d418eSSumit Saxena } 54622d1d418eSSumit Saxena 54632d1d418eSSumit Saxena for (i = 0; i < MPI3MR_NUM_EVTACKCMD; i++) { 54642d1d418eSSumit Saxena if (sc->evtack_cmds[i].reply) { 54652d1d418eSSumit Saxena free(sc->evtack_cmds[i].reply, M_MPI3MR); 54662d1d418eSSumit Saxena sc->evtack_cmds[i].reply = NULL; 54672d1d418eSSumit Saxena } 54682d1d418eSSumit Saxena } 54692d1d418eSSumit Saxena 54702d1d418eSSumit Saxena if (sc->removepend_bitmap) { 54712d1d418eSSumit Saxena free(sc->removepend_bitmap, M_MPI3MR); 54722d1d418eSSumit Saxena sc->removepend_bitmap = NULL; 54732d1d418eSSumit Saxena } 54742d1d418eSSumit Saxena 54752d1d418eSSumit Saxena if (sc->devrem_bitmap) { 54762d1d418eSSumit Saxena free(sc->devrem_bitmap, M_MPI3MR); 54772d1d418eSSumit Saxena sc->devrem_bitmap = NULL; 54782d1d418eSSumit Saxena } 54792d1d418eSSumit Saxena 54802d1d418eSSumit Saxena if (sc->evtack_cmds_bitmap) { 54812d1d418eSSumit Saxena free(sc->evtack_cmds_bitmap, M_MPI3MR); 54822d1d418eSSumit Saxena sc->evtack_cmds_bitmap = NULL; 54832d1d418eSSumit Saxena } 54842d1d418eSSumit Saxena 54852d1d418eSSumit Saxena /* Free Admin reply*/ 54862d1d418eSSumit Saxena if (sc->admin_reply && sc->admin_reply_phys) { 54872d1d418eSSumit Saxena bus_dmamap_unload(sc->admin_reply_tag, sc->admin_reply_dmamap); 54882d1d418eSSumit Saxena bus_dmamem_free(sc->admin_reply_tag, sc->admin_reply, 54892d1d418eSSumit Saxena sc->admin_reply_dmamap); 54902d1d418eSSumit Saxena sc->admin_reply = NULL; 54912d1d418eSSumit Saxena if (sc->admin_reply_tag != NULL) 54922d1d418eSSumit Saxena bus_dma_tag_destroy(sc->admin_reply_tag); 54932d1d418eSSumit Saxena } 54942d1d418eSSumit Saxena 54952d1d418eSSumit Saxena /* Free Admin request*/ 54962d1d418eSSumit Saxena if (sc->admin_req && sc->admin_req_phys) { 54972d1d418eSSumit Saxena bus_dmamap_unload(sc->admin_req_tag, sc->admin_req_dmamap); 54982d1d418eSSumit Saxena bus_dmamem_free(sc->admin_req_tag, sc->admin_req, 54992d1d418eSSumit Saxena sc->admin_req_dmamap); 55002d1d418eSSumit Saxena sc->admin_req = NULL; 55012d1d418eSSumit Saxena if (sc->admin_req_tag != NULL) 55022d1d418eSSumit Saxena bus_dma_tag_destroy(sc->admin_req_tag); 55032d1d418eSSumit Saxena } 55042d1d418eSSumit Saxena mpi3mr_free_ioctl_dma_memory(sc); 55052d1d418eSSumit Saxena 55062d1d418eSSumit Saxena } 55072d1d418eSSumit Saxena 55082d1d418eSSumit Saxena /** 55092d1d418eSSumit Saxena * mpi3mr_drv_cmd_comp_reset - Flush a internal driver command 55102d1d418eSSumit Saxena * @sc: Adapter instance reference 55112d1d418eSSumit Saxena * @cmdptr: Internal command tracker 55122d1d418eSSumit Saxena * 55132d1d418eSSumit Saxena * Complete an internal driver commands with state indicating it 55142d1d418eSSumit Saxena * is completed due to reset. 55152d1d418eSSumit Saxena * 55162d1d418eSSumit Saxena * Return: Nothing. 55172d1d418eSSumit Saxena */ 55182d1d418eSSumit Saxena static inline void mpi3mr_drv_cmd_comp_reset(struct mpi3mr_softc *sc, 55192d1d418eSSumit Saxena struct mpi3mr_drvr_cmd *cmdptr) 55202d1d418eSSumit Saxena { 55212d1d418eSSumit Saxena if (cmdptr->state & MPI3MR_CMD_PENDING) { 55222d1d418eSSumit Saxena cmdptr->state |= MPI3MR_CMD_RESET; 55232d1d418eSSumit Saxena cmdptr->state &= ~MPI3MR_CMD_PENDING; 55242d1d418eSSumit Saxena if (cmdptr->is_waiting) { 55252d1d418eSSumit Saxena complete(&cmdptr->completion); 55262d1d418eSSumit Saxena cmdptr->is_waiting = 0; 55272d1d418eSSumit Saxena } else if (cmdptr->callback) 55282d1d418eSSumit Saxena cmdptr->callback(sc, cmdptr); 55292d1d418eSSumit Saxena } 55302d1d418eSSumit Saxena } 55312d1d418eSSumit Saxena 55322d1d418eSSumit Saxena /** 55332d1d418eSSumit Saxena * mpi3mr_flush_drv_cmds - Flush internal driver commands 55342d1d418eSSumit Saxena * @sc: Adapter instance reference 55352d1d418eSSumit Saxena * 55362d1d418eSSumit Saxena * Flush all internal driver commands post reset 55372d1d418eSSumit Saxena * 55382d1d418eSSumit Saxena * Return: Nothing. 55392d1d418eSSumit Saxena */ 55402d1d418eSSumit Saxena static void mpi3mr_flush_drv_cmds(struct mpi3mr_softc *sc) 55412d1d418eSSumit Saxena { 55422d1d418eSSumit Saxena int i = 0; 55432d1d418eSSumit Saxena struct mpi3mr_drvr_cmd *cmdptr; 55442d1d418eSSumit Saxena 55452d1d418eSSumit Saxena cmdptr = &sc->init_cmds; 55462d1d418eSSumit Saxena mpi3mr_drv_cmd_comp_reset(sc, cmdptr); 55472d1d418eSSumit Saxena 55482d1d418eSSumit Saxena cmdptr = &sc->ioctl_cmds; 55492d1d418eSSumit Saxena mpi3mr_drv_cmd_comp_reset(sc, cmdptr); 55502d1d418eSSumit Saxena 55512d1d418eSSumit Saxena cmdptr = &sc->host_tm_cmds; 55522d1d418eSSumit Saxena mpi3mr_drv_cmd_comp_reset(sc, cmdptr); 55532d1d418eSSumit Saxena 55542d1d418eSSumit Saxena for (i = 0; i < MPI3MR_NUM_DEVRMCMD; i++) { 55552d1d418eSSumit Saxena cmdptr = &sc->dev_rmhs_cmds[i]; 55562d1d418eSSumit Saxena mpi3mr_drv_cmd_comp_reset(sc, cmdptr); 55572d1d418eSSumit Saxena } 55582d1d418eSSumit Saxena 55592d1d418eSSumit Saxena for (i = 0; i < MPI3MR_NUM_EVTACKCMD; i++) { 55602d1d418eSSumit Saxena cmdptr = &sc->evtack_cmds[i]; 55612d1d418eSSumit Saxena mpi3mr_drv_cmd_comp_reset(sc, cmdptr); 55622d1d418eSSumit Saxena } 55632d1d418eSSumit Saxena 55642d1d418eSSumit Saxena cmdptr = &sc->pel_cmds; 55652d1d418eSSumit Saxena mpi3mr_drv_cmd_comp_reset(sc, cmdptr); 55662d1d418eSSumit Saxena 55672d1d418eSSumit Saxena cmdptr = &sc->pel_abort_cmd; 55682d1d418eSSumit Saxena mpi3mr_drv_cmd_comp_reset(sc, cmdptr); 55692d1d418eSSumit Saxena } 55702d1d418eSSumit Saxena 55712d1d418eSSumit Saxena 55722d1d418eSSumit Saxena /** 55732d1d418eSSumit Saxena * mpi3mr_memset_buffers - memset memory for a controller 55742d1d418eSSumit Saxena * @sc: Adapter instance reference 55752d1d418eSSumit Saxena * 55762d1d418eSSumit Saxena * clear all the memory allocated for a controller, typically 55772d1d418eSSumit Saxena * called post reset to reuse the memory allocated during the 55782d1d418eSSumit Saxena * controller init. 55792d1d418eSSumit Saxena * 55802d1d418eSSumit Saxena * Return: Nothing. 55812d1d418eSSumit Saxena */ 55822d1d418eSSumit Saxena static void mpi3mr_memset_buffers(struct mpi3mr_softc *sc) 55832d1d418eSSumit Saxena { 55842d1d418eSSumit Saxena U16 i; 55852d1d418eSSumit Saxena struct mpi3mr_throttle_group_info *tg; 55862d1d418eSSumit Saxena 55872d1d418eSSumit Saxena memset(sc->admin_req, 0, sc->admin_req_q_sz); 55882d1d418eSSumit Saxena memset(sc->admin_reply, 0, sc->admin_reply_q_sz); 55892d1d418eSSumit Saxena 55902d1d418eSSumit Saxena memset(sc->init_cmds.reply, 0, sc->reply_sz); 55912d1d418eSSumit Saxena memset(sc->ioctl_cmds.reply, 0, sc->reply_sz); 55922d1d418eSSumit Saxena memset(sc->host_tm_cmds.reply, 0, sc->reply_sz); 55932d1d418eSSumit Saxena memset(sc->pel_cmds.reply, 0, sc->reply_sz); 55942d1d418eSSumit Saxena memset(sc->pel_abort_cmd.reply, 0, sc->reply_sz); 55952d1d418eSSumit Saxena for (i = 0; i < MPI3MR_NUM_DEVRMCMD; i++) 55962d1d418eSSumit Saxena memset(sc->dev_rmhs_cmds[i].reply, 0, sc->reply_sz); 55972d1d418eSSumit Saxena for (i = 0; i < MPI3MR_NUM_EVTACKCMD; i++) 55982d1d418eSSumit Saxena memset(sc->evtack_cmds[i].reply, 0, sc->reply_sz); 55992d1d418eSSumit Saxena memset(sc->removepend_bitmap, 0, sc->dev_handle_bitmap_sz); 56002d1d418eSSumit Saxena memset(sc->devrem_bitmap, 0, sc->devrem_bitmap_sz); 56012d1d418eSSumit Saxena memset(sc->evtack_cmds_bitmap, 0, sc->evtack_cmds_bitmap_sz); 56022d1d418eSSumit Saxena 56032d1d418eSSumit Saxena for (i = 0; i < sc->num_queues; i++) { 56042d1d418eSSumit Saxena sc->op_reply_q[i].qid = 0; 56052d1d418eSSumit Saxena sc->op_reply_q[i].ci = 0; 56062d1d418eSSumit Saxena sc->op_reply_q[i].num_replies = 0; 56072d1d418eSSumit Saxena sc->op_reply_q[i].ephase = 0; 56082d1d418eSSumit Saxena mpi3mr_atomic_set(&sc->op_reply_q[i].pend_ios, 0); 56092d1d418eSSumit Saxena memset(sc->op_reply_q[i].q_base, 0, sc->op_reply_q[i].qsz); 56102d1d418eSSumit Saxena 56112d1d418eSSumit Saxena sc->op_req_q[i].ci = 0; 56122d1d418eSSumit Saxena sc->op_req_q[i].pi = 0; 56132d1d418eSSumit Saxena sc->op_req_q[i].num_reqs = 0; 56142d1d418eSSumit Saxena sc->op_req_q[i].qid = 0; 56152d1d418eSSumit Saxena sc->op_req_q[i].reply_qid = 0; 56162d1d418eSSumit Saxena memset(sc->op_req_q[i].q_base, 0, sc->op_req_q[i].qsz); 56172d1d418eSSumit Saxena } 56182d1d418eSSumit Saxena 56192d1d418eSSumit Saxena mpi3mr_atomic_set(&sc->pend_large_data_sz, 0); 56202d1d418eSSumit Saxena if (sc->throttle_groups) { 56212d1d418eSSumit Saxena tg = sc->throttle_groups; 56222d1d418eSSumit Saxena for (i = 0; i < sc->num_io_throttle_group; i++, tg++) { 56232d1d418eSSumit Saxena tg->id = 0; 56242d1d418eSSumit Saxena tg->fw_qd = 0; 56252d1d418eSSumit Saxena tg->modified_qd = 0; 56262d1d418eSSumit Saxena tg->io_divert= 0; 56272d1d418eSSumit Saxena tg->high = 0; 56282d1d418eSSumit Saxena tg->low = 0; 56292d1d418eSSumit Saxena mpi3mr_atomic_set(&tg->pend_large_data_sz, 0); 56302d1d418eSSumit Saxena } 56312d1d418eSSumit Saxena } 56322d1d418eSSumit Saxena } 56332d1d418eSSumit Saxena 56342d1d418eSSumit Saxena /** 56352d1d418eSSumit Saxena * mpi3mr_invalidate_devhandles -Invalidate device handles 56362d1d418eSSumit Saxena * @sc: Adapter instance reference 56372d1d418eSSumit Saxena * 56382d1d418eSSumit Saxena * Invalidate the device handles in the target device structures 56392d1d418eSSumit Saxena * . Called post reset prior to reinitializing the controller. 56402d1d418eSSumit Saxena * 56412d1d418eSSumit Saxena * Return: Nothing. 56422d1d418eSSumit Saxena */ 56432d1d418eSSumit Saxena static void mpi3mr_invalidate_devhandles(struct mpi3mr_softc *sc) 56442d1d418eSSumit Saxena { 56452d1d418eSSumit Saxena struct mpi3mr_target *target = NULL; 56462d1d418eSSumit Saxena 56472d1d418eSSumit Saxena mtx_lock_spin(&sc->target_lock); 56482d1d418eSSumit Saxena TAILQ_FOREACH(target, &sc->cam_sc->tgt_list, tgt_next) { 56492d1d418eSSumit Saxena if (target) { 56502d1d418eSSumit Saxena target->dev_handle = MPI3MR_INVALID_DEV_HANDLE; 56512d1d418eSSumit Saxena target->io_throttle_enabled = 0; 56522d1d418eSSumit Saxena target->io_divert = 0; 56532d1d418eSSumit Saxena target->throttle_group = NULL; 56542d1d418eSSumit Saxena } 56552d1d418eSSumit Saxena } 56562d1d418eSSumit Saxena mtx_unlock_spin(&sc->target_lock); 56572d1d418eSSumit Saxena } 56582d1d418eSSumit Saxena 56592d1d418eSSumit Saxena /** 56602d1d418eSSumit Saxena * mpi3mr_rfresh_tgtdevs - Refresh target device exposure 56612d1d418eSSumit Saxena * @sc: Adapter instance reference 56622d1d418eSSumit Saxena * 56632d1d418eSSumit Saxena * This is executed post controller reset to identify any 56642d1d418eSSumit Saxena * missing devices during reset and remove from the upper layers 56652d1d418eSSumit Saxena * or expose any newly detected device to the upper layers. 56662d1d418eSSumit Saxena * 56672d1d418eSSumit Saxena * Return: Nothing. 56682d1d418eSSumit Saxena */ 56692d1d418eSSumit Saxena 56702d1d418eSSumit Saxena static void mpi3mr_rfresh_tgtdevs(struct mpi3mr_softc *sc) 56712d1d418eSSumit Saxena { 56722d1d418eSSumit Saxena struct mpi3mr_target *target = NULL; 56732d1d418eSSumit Saxena struct mpi3mr_target *target_temp = NULL; 56742d1d418eSSumit Saxena 56752d1d418eSSumit Saxena TAILQ_FOREACH_SAFE(target, &sc->cam_sc->tgt_list, tgt_next, target_temp) { 56762d1d418eSSumit Saxena if (target->dev_handle == MPI3MR_INVALID_DEV_HANDLE) { 56772d1d418eSSumit Saxena if (target->exposed_to_os) 56782d1d418eSSumit Saxena mpi3mr_remove_device_from_os(sc, target->dev_handle); 56792d1d418eSSumit Saxena mpi3mr_remove_device_from_list(sc, target, true); 56800d705645SChandrakanth patil } else if (target->is_hidden && target->exposed_to_os) { 56810d705645SChandrakanth patil mpi3mr_remove_device_from_os(sc, target->dev_handle); 56822d1d418eSSumit Saxena } 56832d1d418eSSumit Saxena } 56842d1d418eSSumit Saxena 56852d1d418eSSumit Saxena TAILQ_FOREACH(target, &sc->cam_sc->tgt_list, tgt_next) { 56862d1d418eSSumit Saxena if ((target->dev_handle != MPI3MR_INVALID_DEV_HANDLE) && 56872d1d418eSSumit Saxena !target->is_hidden && !target->exposed_to_os) { 56882d1d418eSSumit Saxena mpi3mr_add_device(sc, target->per_id); 56892d1d418eSSumit Saxena } 56902d1d418eSSumit Saxena } 56912d1d418eSSumit Saxena 56922d1d418eSSumit Saxena } 56932d1d418eSSumit Saxena 56942d1d418eSSumit Saxena static void mpi3mr_flush_io(struct mpi3mr_softc *sc) 56952d1d418eSSumit Saxena { 56962d1d418eSSumit Saxena int i; 56972d1d418eSSumit Saxena struct mpi3mr_cmd *cmd = NULL; 56982d1d418eSSumit Saxena union ccb *ccb = NULL; 56992d1d418eSSumit Saxena 57002d1d418eSSumit Saxena for (i = 0; i < sc->max_host_ios; i++) { 57012d1d418eSSumit Saxena cmd = sc->cmd_list[i]; 57022d1d418eSSumit Saxena 57032d1d418eSSumit Saxena if (cmd && cmd->ccb) { 57042d1d418eSSumit Saxena if (cmd->callout_owner) { 57052d1d418eSSumit Saxena ccb = (union ccb *)(cmd->ccb); 57062d1d418eSSumit Saxena ccb->ccb_h.status = CAM_SCSI_BUS_RESET; 5707571f1d06SChandrakanth patil mpi3mr_atomic_dec(&sc->fw_outstanding); 5708571f1d06SChandrakanth patil mpi3mr_atomic_dec(&cmd->targ->outstanding); 57092d1d418eSSumit Saxena mpi3mr_cmd_done(sc, cmd); 57102d1d418eSSumit Saxena } else { 57112d1d418eSSumit Saxena cmd->ccb = NULL; 57122d1d418eSSumit Saxena mpi3mr_release_command(cmd); 57132d1d418eSSumit Saxena } 57142d1d418eSSumit Saxena } 57152d1d418eSSumit Saxena } 57162d1d418eSSumit Saxena } 57172d1d418eSSumit Saxena /** 57182d1d418eSSumit Saxena * mpi3mr_clear_reset_history - Clear reset history 57192d1d418eSSumit Saxena * @sc: Adapter instance reference 57202d1d418eSSumit Saxena * 57212d1d418eSSumit Saxena * Write the reset history bit in IOC Status to clear the bit, 57222d1d418eSSumit Saxena * if it is already set. 57232d1d418eSSumit Saxena * 57242d1d418eSSumit Saxena * Return: Nothing. 57252d1d418eSSumit Saxena */ 57262d1d418eSSumit Saxena static inline void mpi3mr_clear_reset_history(struct mpi3mr_softc *sc) 57272d1d418eSSumit Saxena { 57282d1d418eSSumit Saxena U32 ioc_status; 57292d1d418eSSumit Saxena 57302d1d418eSSumit Saxena ioc_status = mpi3mr_regread(sc, MPI3_SYSIF_IOC_STATUS_OFFSET); 57312d1d418eSSumit Saxena if (ioc_status & MPI3_SYSIF_IOC_STATUS_RESET_HISTORY) 57322d1d418eSSumit Saxena mpi3mr_regwrite(sc, MPI3_SYSIF_IOC_STATUS_OFFSET, ioc_status); 57332d1d418eSSumit Saxena } 57342d1d418eSSumit Saxena 57352d1d418eSSumit Saxena /** 57362d1d418eSSumit Saxena * mpi3mr_set_diagsave - Set diag save bit for snapdump 57372d1d418eSSumit Saxena * @sc: Adapter reference 57382d1d418eSSumit Saxena * 57392d1d418eSSumit Saxena * Set diag save bit in IOC configuration register to enable 57402d1d418eSSumit Saxena * snapdump. 57412d1d418eSSumit Saxena * 57422d1d418eSSumit Saxena * Return: Nothing. 57432d1d418eSSumit Saxena */ 57442d1d418eSSumit Saxena static inline void mpi3mr_set_diagsave(struct mpi3mr_softc *sc) 57452d1d418eSSumit Saxena { 57462d1d418eSSumit Saxena U32 ioc_config; 57472d1d418eSSumit Saxena 57482d1d418eSSumit Saxena ioc_config = 57492d1d418eSSumit Saxena mpi3mr_regread(sc, MPI3_SYSIF_IOC_CONFIG_OFFSET); 57502d1d418eSSumit Saxena ioc_config |= MPI3_SYSIF_IOC_CONFIG_DIAG_SAVE; 57512d1d418eSSumit Saxena mpi3mr_regwrite(sc, MPI3_SYSIF_IOC_CONFIG_OFFSET, ioc_config); 57522d1d418eSSumit Saxena } 57532d1d418eSSumit Saxena 57542d1d418eSSumit Saxena /** 57552d1d418eSSumit Saxena * mpi3mr_issue_reset - Issue reset to the controller 57562d1d418eSSumit Saxena * @sc: Adapter reference 57572d1d418eSSumit Saxena * @reset_type: Reset type 57582d1d418eSSumit Saxena * @reset_reason: Reset reason code 57592d1d418eSSumit Saxena * 57602d1d418eSSumit Saxena * Unlock the host diagnostic registers and write the specific 57612d1d418eSSumit Saxena * reset type to that, wait for reset acknowledgement from the 57622d1d418eSSumit Saxena * controller, if the reset is not successful retry for the 57632d1d418eSSumit Saxena * predefined number of times. 57642d1d418eSSumit Saxena * 57652d1d418eSSumit Saxena * Return: 0 on success, non-zero on failure. 57662d1d418eSSumit Saxena */ 57672d1d418eSSumit Saxena static int mpi3mr_issue_reset(struct mpi3mr_softc *sc, U16 reset_type, 57682d1d418eSSumit Saxena U32 reset_reason) 57692d1d418eSSumit Saxena { 57702d1d418eSSumit Saxena int retval = -1; 57712d1d418eSSumit Saxena U8 unlock_retry_count = 0; 57722d1d418eSSumit Saxena U32 host_diagnostic, ioc_status, ioc_config; 57732d1d418eSSumit Saxena U32 timeout = MPI3MR_RESET_ACK_TIMEOUT * 10; 57742d1d418eSSumit Saxena 57752d1d418eSSumit Saxena if ((reset_type != MPI3_SYSIF_HOST_DIAG_RESET_ACTION_SOFT_RESET) && 57762d1d418eSSumit Saxena (reset_type != MPI3_SYSIF_HOST_DIAG_RESET_ACTION_DIAG_FAULT)) 57772d1d418eSSumit Saxena return retval; 57782d1d418eSSumit Saxena if (sc->unrecoverable) 57792d1d418eSSumit Saxena return retval; 57802d1d418eSSumit Saxena 57812d1d418eSSumit Saxena if (reset_reason == MPI3MR_RESET_FROM_FIRMWARE) { 57822d1d418eSSumit Saxena retval = 0; 57832d1d418eSSumit Saxena return retval; 57842d1d418eSSumit Saxena } 57852d1d418eSSumit Saxena 57862d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_INFO, "%s reset due to %s(0x%x)\n", 57872d1d418eSSumit Saxena mpi3mr_reset_type_name(reset_type), 57882d1d418eSSumit Saxena mpi3mr_reset_rc_name(reset_reason), reset_reason); 57892d1d418eSSumit Saxena 57902d1d418eSSumit Saxena mpi3mr_clear_reset_history(sc); 57912d1d418eSSumit Saxena do { 57922d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_INFO, 57932d1d418eSSumit Saxena "Write magic sequence to unlock host diag register (retry=%d)\n", 57942d1d418eSSumit Saxena ++unlock_retry_count); 57952d1d418eSSumit Saxena if (unlock_retry_count >= MPI3MR_HOSTDIAG_UNLOCK_RETRY_COUNT) { 57962d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_ERROR, 57972d1d418eSSumit Saxena "%s reset failed! due to host diag register unlock failure" 57982d1d418eSSumit Saxena "host_diagnostic(0x%08x)\n", mpi3mr_reset_type_name(reset_type), 57992d1d418eSSumit Saxena host_diagnostic); 58002d1d418eSSumit Saxena sc->unrecoverable = 1; 58012d1d418eSSumit Saxena return retval; 58022d1d418eSSumit Saxena } 58032d1d418eSSumit Saxena 58042d1d418eSSumit Saxena mpi3mr_regwrite(sc, MPI3_SYSIF_WRITE_SEQUENCE_OFFSET, 58052d1d418eSSumit Saxena MPI3_SYSIF_WRITE_SEQUENCE_KEY_VALUE_FLUSH); 58062d1d418eSSumit Saxena mpi3mr_regwrite(sc, MPI3_SYSIF_WRITE_SEQUENCE_OFFSET, 58072d1d418eSSumit Saxena MPI3_SYSIF_WRITE_SEQUENCE_KEY_VALUE_1ST); 58082d1d418eSSumit Saxena mpi3mr_regwrite(sc, MPI3_SYSIF_WRITE_SEQUENCE_OFFSET, 58092d1d418eSSumit Saxena MPI3_SYSIF_WRITE_SEQUENCE_KEY_VALUE_2ND); 58102d1d418eSSumit Saxena mpi3mr_regwrite(sc, MPI3_SYSIF_WRITE_SEQUENCE_OFFSET, 58112d1d418eSSumit Saxena MPI3_SYSIF_WRITE_SEQUENCE_KEY_VALUE_3RD); 58122d1d418eSSumit Saxena mpi3mr_regwrite(sc, MPI3_SYSIF_WRITE_SEQUENCE_OFFSET, 58132d1d418eSSumit Saxena MPI3_SYSIF_WRITE_SEQUENCE_KEY_VALUE_4TH); 58142d1d418eSSumit Saxena mpi3mr_regwrite(sc, MPI3_SYSIF_WRITE_SEQUENCE_OFFSET, 58152d1d418eSSumit Saxena MPI3_SYSIF_WRITE_SEQUENCE_KEY_VALUE_5TH); 58162d1d418eSSumit Saxena mpi3mr_regwrite(sc, MPI3_SYSIF_WRITE_SEQUENCE_OFFSET, 58172d1d418eSSumit Saxena MPI3_SYSIF_WRITE_SEQUENCE_KEY_VALUE_6TH); 58182d1d418eSSumit Saxena 58192d1d418eSSumit Saxena DELAY(1000); /* delay in usec */ 58202d1d418eSSumit Saxena host_diagnostic = mpi3mr_regread(sc, MPI3_SYSIF_HOST_DIAG_OFFSET); 58212d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_INFO, 58222d1d418eSSumit Saxena "wrote magic sequence: retry_count(%d), host_diagnostic(0x%08x)\n", 58232d1d418eSSumit Saxena unlock_retry_count, host_diagnostic); 58242d1d418eSSumit Saxena } while (!(host_diagnostic & MPI3_SYSIF_HOST_DIAG_DIAG_WRITE_ENABLE)); 58252d1d418eSSumit Saxena 58262d1d418eSSumit Saxena mpi3mr_regwrite(sc, MPI3_SYSIF_SCRATCHPAD0_OFFSET, reset_reason); 58272d1d418eSSumit Saxena mpi3mr_regwrite(sc, MPI3_SYSIF_HOST_DIAG_OFFSET, host_diagnostic | reset_type); 58282d1d418eSSumit Saxena 58292d1d418eSSumit Saxena if (reset_type == MPI3_SYSIF_HOST_DIAG_RESET_ACTION_SOFT_RESET) { 58302d1d418eSSumit Saxena do { 58312d1d418eSSumit Saxena ioc_status = mpi3mr_regread(sc, MPI3_SYSIF_IOC_STATUS_OFFSET); 58322d1d418eSSumit Saxena if (ioc_status & 58332d1d418eSSumit Saxena MPI3_SYSIF_IOC_STATUS_RESET_HISTORY) { 58342d1d418eSSumit Saxena ioc_config = 58352d1d418eSSumit Saxena mpi3mr_regread(sc, MPI3_SYSIF_IOC_CONFIG_OFFSET); 58362d1d418eSSumit Saxena if (mpi3mr_soft_reset_success(ioc_status, 58372d1d418eSSumit Saxena ioc_config)) { 58382d1d418eSSumit Saxena mpi3mr_clear_reset_history(sc); 58392d1d418eSSumit Saxena retval = 0; 58402d1d418eSSumit Saxena break; 58412d1d418eSSumit Saxena } 58422d1d418eSSumit Saxena } 58432d1d418eSSumit Saxena DELAY(100 * 1000); 58442d1d418eSSumit Saxena } while (--timeout); 58452d1d418eSSumit Saxena } else if (reset_type == MPI3_SYSIF_HOST_DIAG_RESET_ACTION_DIAG_FAULT) { 58462d1d418eSSumit Saxena do { 58472d1d418eSSumit Saxena ioc_status = mpi3mr_regread(sc, MPI3_SYSIF_IOC_STATUS_OFFSET); 58482d1d418eSSumit Saxena if (mpi3mr_diagfault_success(sc, ioc_status)) { 58492d1d418eSSumit Saxena retval = 0; 58502d1d418eSSumit Saxena break; 58512d1d418eSSumit Saxena } 58522d1d418eSSumit Saxena DELAY(100 * 1000); 58532d1d418eSSumit Saxena } while (--timeout); 58542d1d418eSSumit Saxena } 58552d1d418eSSumit Saxena 58562d1d418eSSumit Saxena mpi3mr_regwrite(sc, MPI3_SYSIF_WRITE_SEQUENCE_OFFSET, 58572d1d418eSSumit Saxena MPI3_SYSIF_WRITE_SEQUENCE_KEY_VALUE_2ND); 58582d1d418eSSumit Saxena 58592d1d418eSSumit Saxena ioc_status = mpi3mr_regread(sc, MPI3_SYSIF_IOC_STATUS_OFFSET); 58602d1d418eSSumit Saxena ioc_config = mpi3mr_regread(sc, MPI3_SYSIF_IOC_CONFIG_OFFSET); 58612d1d418eSSumit Saxena 58622d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_INFO, 58632d1d418eSSumit Saxena "IOC Status/Config after %s reset is (0x%x)/(0x%x)\n", 58642d1d418eSSumit Saxena !retval ? "successful":"failed", ioc_status, 58652d1d418eSSumit Saxena ioc_config); 58662d1d418eSSumit Saxena 58672d1d418eSSumit Saxena if (retval) 58682d1d418eSSumit Saxena sc->unrecoverable = 1; 58692d1d418eSSumit Saxena 58702d1d418eSSumit Saxena return retval; 58712d1d418eSSumit Saxena } 58722d1d418eSSumit Saxena 58732d1d418eSSumit Saxena inline void mpi3mr_cleanup_event_taskq(struct mpi3mr_softc *sc) 58742d1d418eSSumit Saxena { 5875b411372bSWarner Losh /* 5876b411372bSWarner Losh * Block the taskqueue before draining. This means any new tasks won't 5877272a4060SWarner Losh * be queued to the taskqueue worker thread. But it doesn't stop the 5878272a4060SWarner Losh * current workers that are running. taskqueue_drain waits for those 5879272a4060SWarner Losh * correctly in the case of thread backed taskqueues. The while loop 5880272a4060SWarner Losh * ensures that all taskqueue threads have finished their current tasks. 5881b411372bSWarner Losh */ 58822d1d418eSSumit Saxena taskqueue_block(sc->cam_sc->ev_tq); 5883272a4060SWarner Losh while (taskqueue_cancel(sc->cam_sc->ev_tq, &sc->cam_sc->ev_task, NULL) != 0) { 5884b411372bSWarner Losh taskqueue_drain(sc->cam_sc->ev_tq, &sc->cam_sc->ev_task); 58852d1d418eSSumit Saxena } 5886272a4060SWarner Losh } 58872d1d418eSSumit Saxena 58882d1d418eSSumit Saxena /** 58892d1d418eSSumit Saxena * mpi3mr_soft_reset_handler - Reset the controller 58902d1d418eSSumit Saxena * @sc: Adapter instance reference 58912d1d418eSSumit Saxena * @reset_reason: Reset reason code 58922d1d418eSSumit Saxena * @snapdump: snapdump enable/disbale bit 58932d1d418eSSumit Saxena * 58942d1d418eSSumit Saxena * This is an handler for recovering controller by issuing soft 58952d1d418eSSumit Saxena * reset or diag fault reset. This is a blocking function and 58962d1d418eSSumit Saxena * when one reset is executed if any other resets they will be 58972d1d418eSSumit Saxena * blocked. All IOCTLs/IO will be blocked during the reset. If 58982d1d418eSSumit Saxena * controller reset is successful then the controller will be 58992d1d418eSSumit Saxena * reinitalized, otherwise the controller will be marked as not 59002d1d418eSSumit Saxena * recoverable 59012d1d418eSSumit Saxena * 59022d1d418eSSumit Saxena * Return: 0 on success, non-zero on failure. 59032d1d418eSSumit Saxena */ 59042d1d418eSSumit Saxena int mpi3mr_soft_reset_handler(struct mpi3mr_softc *sc, 59052d1d418eSSumit Saxena U32 reset_reason, bool snapdump) 59062d1d418eSSumit Saxena { 59072d1d418eSSumit Saxena int retval = 0, i = 0; 59082d1d418eSSumit Saxena enum mpi3mr_iocstate ioc_state; 59092d1d418eSSumit Saxena 59102d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_INFO, "soft reset invoked: reason code: %s\n", 59112d1d418eSSumit Saxena mpi3mr_reset_rc_name(reset_reason)); 59122d1d418eSSumit Saxena 59132d1d418eSSumit Saxena if ((reset_reason == MPI3MR_RESET_FROM_IOCTL) && 59142d1d418eSSumit Saxena (sc->reset.ioctl_reset_snapdump != true)) 59152d1d418eSSumit Saxena snapdump = false; 59162d1d418eSSumit Saxena 59172d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_INFO, 59182d1d418eSSumit Saxena "soft_reset_handler: wait if diag save is in progress\n"); 59192d1d418eSSumit Saxena while (sc->diagsave_timeout) 59202d1d418eSSumit Saxena DELAY(1000 * 1000); 59212d1d418eSSumit Saxena 59222d1d418eSSumit Saxena ioc_state = mpi3mr_get_iocstate(sc); 59232d1d418eSSumit Saxena if (ioc_state == MRIOC_STATE_UNRECOVERABLE) { 59242d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_ERROR, "controller is in unrecoverable state, exit\n"); 59252d1d418eSSumit Saxena sc->reset.type = MPI3MR_NO_RESET; 59262d1d418eSSumit Saxena sc->reset.reason = MPI3MR_DEFAULT_RESET_REASON; 59272d1d418eSSumit Saxena sc->reset.status = -1; 59282d1d418eSSumit Saxena sc->reset.ioctl_reset_snapdump = false; 59292d1d418eSSumit Saxena return -1; 59302d1d418eSSumit Saxena } 59312d1d418eSSumit Saxena 59322d1d418eSSumit Saxena if (sc->reset_in_progress) { 59332d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_INFO, "reset is already in progress, exit\n"); 59342d1d418eSSumit Saxena return -1; 59352d1d418eSSumit Saxena } 59362d1d418eSSumit Saxena 59372d1d418eSSumit Saxena /* Pause IOs, drain and block the event taskqueue */ 59382d1d418eSSumit Saxena xpt_freeze_simq(sc->cam_sc->sim, 1); 59392d1d418eSSumit Saxena 59402d1d418eSSumit Saxena mpi3mr_cleanup_event_taskq(sc); 59412d1d418eSSumit Saxena 59422d1d418eSSumit Saxena sc->reset_in_progress = 1; 59432d1d418eSSumit Saxena sc->block_ioctls = 1; 59442d1d418eSSumit Saxena 59452d1d418eSSumit Saxena while (mpi3mr_atomic_read(&sc->pend_ioctls) && (i < PEND_IOCTLS_COMP_WAIT_TIME)) { 59462d1d418eSSumit Saxena ioc_state = mpi3mr_get_iocstate(sc); 59472d1d418eSSumit Saxena if (ioc_state == MRIOC_STATE_FAULT) 59482d1d418eSSumit Saxena break; 59492d1d418eSSumit Saxena i++; 59502d1d418eSSumit Saxena if (!(i % 5)) { 59512d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_INFO, 59522d1d418eSSumit Saxena "[%2ds]waiting for IOCTL to be finished from %s\n", i, __func__); 59532d1d418eSSumit Saxena } 59542d1d418eSSumit Saxena DELAY(1000 * 1000); 59552d1d418eSSumit Saxena } 59562d1d418eSSumit Saxena 59572d1d418eSSumit Saxena if ((!snapdump) && (reset_reason != MPI3MR_RESET_FROM_FAULT_WATCH) && 59582d1d418eSSumit Saxena (reset_reason != MPI3MR_RESET_FROM_FIRMWARE) && 59592d1d418eSSumit Saxena (reset_reason != MPI3MR_RESET_FROM_CIACTIV_FAULT)) { 59602d1d418eSSumit Saxena 59612d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_INFO, "Turn off events prior to reset\n"); 59622d1d418eSSumit Saxena 59632d1d418eSSumit Saxena for (i = 0; i < MPI3_EVENT_NOTIFY_EVENTMASK_WORDS; i++) 59642d1d418eSSumit Saxena sc->event_masks[i] = -1; 59652d1d418eSSumit Saxena mpi3mr_issue_event_notification(sc); 59662d1d418eSSumit Saxena } 59672d1d418eSSumit Saxena 59682d1d418eSSumit Saxena mpi3mr_disable_interrupts(sc); 59692d1d418eSSumit Saxena 59702d1d418eSSumit Saxena if (snapdump) 59712d1d418eSSumit Saxena mpi3mr_trigger_snapdump(sc, reset_reason); 59722d1d418eSSumit Saxena 59732d1d418eSSumit Saxena retval = mpi3mr_issue_reset(sc, 59742d1d418eSSumit Saxena MPI3_SYSIF_HOST_DIAG_RESET_ACTION_SOFT_RESET, reset_reason); 59752d1d418eSSumit Saxena if (retval) { 59762d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_ERROR, "Failed to issue soft reset to the ioc\n"); 59772d1d418eSSumit Saxena goto out; 59782d1d418eSSumit Saxena } 59792d1d418eSSumit Saxena 59802d1d418eSSumit Saxena mpi3mr_flush_drv_cmds(sc); 59812d1d418eSSumit Saxena mpi3mr_flush_io(sc); 59822d1d418eSSumit Saxena mpi3mr_invalidate_devhandles(sc); 59832d1d418eSSumit Saxena mpi3mr_memset_buffers(sc); 59842d1d418eSSumit Saxena 59852d1d418eSSumit Saxena if (sc->prepare_for_reset) { 59862d1d418eSSumit Saxena sc->prepare_for_reset = 0; 59872d1d418eSSumit Saxena sc->prepare_for_reset_timeout_counter = 0; 59882d1d418eSSumit Saxena } 59892d1d418eSSumit Saxena 59902d1d418eSSumit Saxena retval = mpi3mr_initialize_ioc(sc, MPI3MR_INIT_TYPE_RESET); 59912d1d418eSSumit Saxena if (retval) { 59922d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_ERROR, "reinit after soft reset failed: reason %d\n", 59932d1d418eSSumit Saxena reset_reason); 59942d1d418eSSumit Saxena goto out; 59952d1d418eSSumit Saxena } 59962d1d418eSSumit Saxena 59972d1d418eSSumit Saxena DELAY((1000 * 1000) * 10); 59982d1d418eSSumit Saxena out: 59992d1d418eSSumit Saxena if (!retval) { 60002d1d418eSSumit Saxena sc->diagsave_timeout = 0; 60012d1d418eSSumit Saxena sc->reset_in_progress = 0; 60022d1d418eSSumit Saxena mpi3mr_rfresh_tgtdevs(sc); 60032d1d418eSSumit Saxena sc->ts_update_counter = 0; 60042d1d418eSSumit Saxena sc->block_ioctls = 0; 60052d1d418eSSumit Saxena sc->pel_abort_requested = 0; 60062d1d418eSSumit Saxena if (sc->pel_wait_pend) { 60072d1d418eSSumit Saxena sc->pel_cmds.retry_count = 0; 60082d1d418eSSumit Saxena mpi3mr_issue_pel_wait(sc, &sc->pel_cmds); 60092d1d418eSSumit Saxena mpi3mr_app_send_aen(sc); 60102d1d418eSSumit Saxena } 60112d1d418eSSumit Saxena } else { 60122d1d418eSSumit Saxena mpi3mr_issue_reset(sc, 60132d1d418eSSumit Saxena MPI3_SYSIF_HOST_DIAG_RESET_ACTION_DIAG_FAULT, reset_reason); 60142d1d418eSSumit Saxena sc->unrecoverable = 1; 60152d1d418eSSumit Saxena sc->reset_in_progress = 0; 60162d1d418eSSumit Saxena } 60172d1d418eSSumit Saxena 60182d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_INFO, "Soft Reset: %s\n", ((retval == 0) ? "SUCCESS" : "FAILED")); 60192d1d418eSSumit Saxena 60202d1d418eSSumit Saxena taskqueue_unblock(sc->cam_sc->ev_tq); 60212d1d418eSSumit Saxena xpt_release_simq(sc->cam_sc->sim, 1); 60222d1d418eSSumit Saxena 60232d1d418eSSumit Saxena sc->reset.type = MPI3MR_NO_RESET; 60242d1d418eSSumit Saxena sc->reset.reason = MPI3MR_DEFAULT_RESET_REASON; 60252d1d418eSSumit Saxena sc->reset.status = retval; 60262d1d418eSSumit Saxena sc->reset.ioctl_reset_snapdump = false; 60272d1d418eSSumit Saxena 60282d1d418eSSumit Saxena return retval; 60292d1d418eSSumit Saxena } 60302d1d418eSSumit Saxena 60312d1d418eSSumit Saxena /** 60322d1d418eSSumit Saxena * mpi3mr_issue_ioc_shutdown - shutdown controller 60332d1d418eSSumit Saxena * @sc: Adapter instance reference 60342d1d418eSSumit Saxena * 60352d1d418eSSumit Saxena * Send shutodwn notification to the controller and wait for the 60362d1d418eSSumit Saxena * shutdown_timeout for it to be completed. 60372d1d418eSSumit Saxena * 60382d1d418eSSumit Saxena * Return: Nothing. 60392d1d418eSSumit Saxena */ 60402d1d418eSSumit Saxena static void mpi3mr_issue_ioc_shutdown(struct mpi3mr_softc *sc) 60412d1d418eSSumit Saxena { 60422d1d418eSSumit Saxena U32 ioc_config, ioc_status; 60432d1d418eSSumit Saxena U8 retval = 1, retry = 0; 60442d1d418eSSumit Saxena U32 timeout = MPI3MR_DEFAULT_SHUTDOWN_TIME * 10; 60452d1d418eSSumit Saxena 60462d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_INFO, "sending shutdown notification\n"); 60472d1d418eSSumit Saxena if (sc->unrecoverable) { 60482d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_ERROR, 60492d1d418eSSumit Saxena "controller is unrecoverable, shutdown not issued\n"); 60502d1d418eSSumit Saxena return; 60512d1d418eSSumit Saxena } 60522d1d418eSSumit Saxena ioc_status = mpi3mr_regread(sc, MPI3_SYSIF_IOC_STATUS_OFFSET); 60532d1d418eSSumit Saxena if ((ioc_status & MPI3_SYSIF_IOC_STATUS_SHUTDOWN_MASK) 60542d1d418eSSumit Saxena == MPI3_SYSIF_IOC_STATUS_SHUTDOWN_IN_PROGRESS) { 60552d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_ERROR, "shutdown already in progress\n"); 60562d1d418eSSumit Saxena return; 60572d1d418eSSumit Saxena } 60582d1d418eSSumit Saxena 60592d1d418eSSumit Saxena ioc_config = mpi3mr_regread(sc, MPI3_SYSIF_IOC_CONFIG_OFFSET); 60602d1d418eSSumit Saxena ioc_config |= MPI3_SYSIF_IOC_CONFIG_SHUTDOWN_NORMAL; 60612d1d418eSSumit Saxena ioc_config |= MPI3_SYSIF_IOC_CONFIG_DEVICE_SHUTDOWN_SEND_REQ; 60622d1d418eSSumit Saxena 60632d1d418eSSumit Saxena mpi3mr_regwrite(sc, MPI3_SYSIF_IOC_CONFIG_OFFSET, ioc_config); 60642d1d418eSSumit Saxena 60652d1d418eSSumit Saxena if (sc->facts.shutdown_timeout) 60662d1d418eSSumit Saxena timeout = sc->facts.shutdown_timeout * 10; 60672d1d418eSSumit Saxena 60682d1d418eSSumit Saxena do { 60692d1d418eSSumit Saxena ioc_status = mpi3mr_regread(sc, MPI3_SYSIF_IOC_STATUS_OFFSET); 60702d1d418eSSumit Saxena if ((ioc_status & MPI3_SYSIF_IOC_STATUS_SHUTDOWN_MASK) 60712d1d418eSSumit Saxena == MPI3_SYSIF_IOC_STATUS_SHUTDOWN_COMPLETE) { 60722d1d418eSSumit Saxena retval = 0; 60732d1d418eSSumit Saxena break; 60742d1d418eSSumit Saxena } 60752d1d418eSSumit Saxena 60762d1d418eSSumit Saxena if (sc->unrecoverable) 60772d1d418eSSumit Saxena break; 60782d1d418eSSumit Saxena 60792d1d418eSSumit Saxena if ((ioc_status & MPI3_SYSIF_IOC_STATUS_FAULT)) { 60802d1d418eSSumit Saxena mpi3mr_print_fault_info(sc); 60812d1d418eSSumit Saxena 60822d1d418eSSumit Saxena if (retry >= MPI3MR_MAX_SHUTDOWN_RETRY_COUNT) 60832d1d418eSSumit Saxena break; 60842d1d418eSSumit Saxena 60852d1d418eSSumit Saxena if (mpi3mr_issue_reset(sc, 60862d1d418eSSumit Saxena MPI3_SYSIF_HOST_DIAG_RESET_ACTION_SOFT_RESET, 60872d1d418eSSumit Saxena MPI3MR_RESET_FROM_CTLR_CLEANUP)) 60882d1d418eSSumit Saxena break; 60892d1d418eSSumit Saxena 60902d1d418eSSumit Saxena ioc_config = mpi3mr_regread(sc, MPI3_SYSIF_IOC_CONFIG_OFFSET); 60912d1d418eSSumit Saxena ioc_config |= MPI3_SYSIF_IOC_CONFIG_SHUTDOWN_NORMAL; 60922d1d418eSSumit Saxena ioc_config |= MPI3_SYSIF_IOC_CONFIG_DEVICE_SHUTDOWN_SEND_REQ; 60932d1d418eSSumit Saxena 60942d1d418eSSumit Saxena mpi3mr_regwrite(sc, MPI3_SYSIF_IOC_CONFIG_OFFSET, ioc_config); 60952d1d418eSSumit Saxena 60962d1d418eSSumit Saxena if (sc->facts.shutdown_timeout) 60972d1d418eSSumit Saxena timeout = sc->facts.shutdown_timeout * 10; 60982d1d418eSSumit Saxena 60992d1d418eSSumit Saxena retry++; 61002d1d418eSSumit Saxena } 61012d1d418eSSumit Saxena 61022d1d418eSSumit Saxena DELAY(100 * 1000); 61032d1d418eSSumit Saxena 61042d1d418eSSumit Saxena } while (--timeout); 61052d1d418eSSumit Saxena 61062d1d418eSSumit Saxena ioc_status = mpi3mr_regread(sc, MPI3_SYSIF_IOC_STATUS_OFFSET); 61072d1d418eSSumit Saxena ioc_config = mpi3mr_regread(sc, MPI3_SYSIF_IOC_CONFIG_OFFSET); 61082d1d418eSSumit Saxena 61092d1d418eSSumit Saxena if (retval) { 61102d1d418eSSumit Saxena if ((ioc_status & MPI3_SYSIF_IOC_STATUS_SHUTDOWN_MASK) 61112d1d418eSSumit Saxena == MPI3_SYSIF_IOC_STATUS_SHUTDOWN_IN_PROGRESS) 61122d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_ERROR, 61132d1d418eSSumit Saxena "shutdown still in progress after timeout\n"); 61142d1d418eSSumit Saxena } 61152d1d418eSSumit Saxena 61162d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_INFO, 61172d1d418eSSumit Saxena "ioc_status/ioc_config after %s shutdown is (0x%x)/(0x%x)\n", 61182d1d418eSSumit Saxena (!retval)?"successful":"failed", ioc_status, 61192d1d418eSSumit Saxena ioc_config); 61202d1d418eSSumit Saxena } 61212d1d418eSSumit Saxena 61222d1d418eSSumit Saxena /** 61232d1d418eSSumit Saxena * mpi3mr_cleanup_ioc - Cleanup controller 61242d1d418eSSumit Saxena * @sc: Adapter instance reference 61252d1d418eSSumit Saxena 61262d1d418eSSumit Saxena * controller cleanup handler, Message unit reset or soft reset 61272d1d418eSSumit Saxena * and shutdown notification is issued to the controller. 61282d1d418eSSumit Saxena * 61292d1d418eSSumit Saxena * Return: Nothing. 61302d1d418eSSumit Saxena */ 61312d1d418eSSumit Saxena void mpi3mr_cleanup_ioc(struct mpi3mr_softc *sc) 61322d1d418eSSumit Saxena { 61332d1d418eSSumit Saxena enum mpi3mr_iocstate ioc_state; 61342d1d418eSSumit Saxena 61352d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_INFO, "cleaning up the controller\n"); 61362d1d418eSSumit Saxena mpi3mr_disable_interrupts(sc); 61372d1d418eSSumit Saxena 61382d1d418eSSumit Saxena ioc_state = mpi3mr_get_iocstate(sc); 61392d1d418eSSumit Saxena 61402d1d418eSSumit Saxena if ((!sc->unrecoverable) && (!sc->reset_in_progress) && 61412d1d418eSSumit Saxena (ioc_state == MRIOC_STATE_READY)) { 61422d1d418eSSumit Saxena if (mpi3mr_mur_ioc(sc, 61432d1d418eSSumit Saxena MPI3MR_RESET_FROM_CTLR_CLEANUP)) 61442d1d418eSSumit Saxena mpi3mr_issue_reset(sc, 61452d1d418eSSumit Saxena MPI3_SYSIF_HOST_DIAG_RESET_ACTION_SOFT_RESET, 61462d1d418eSSumit Saxena MPI3MR_RESET_FROM_MUR_FAILURE); 61472d1d418eSSumit Saxena mpi3mr_issue_ioc_shutdown(sc); 61482d1d418eSSumit Saxena } 61492d1d418eSSumit Saxena 61502d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_INFO, "controller cleanup completed\n"); 61512d1d418eSSumit Saxena } 6152