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