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