1*2d1d418eSSumit Saxena /* 2*2d1d418eSSumit Saxena * SPDX-License-Identifier: BSD-2-Clause 3*2d1d418eSSumit Saxena * 4*2d1d418eSSumit Saxena * Copyright (c) 2020-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/selinfo.h> 52*2d1d418eSSumit Saxena #include <sys/module.h> 53*2d1d418eSSumit Saxena #include <sys/bus.h> 54*2d1d418eSSumit Saxena #include <sys/conf.h> 55*2d1d418eSSumit Saxena #include <sys/bio.h> 56*2d1d418eSSumit Saxena #include <sys/malloc.h> 57*2d1d418eSSumit Saxena #include <sys/uio.h> 58*2d1d418eSSumit Saxena #include <sys/sysctl.h> 59*2d1d418eSSumit Saxena #include <sys/endian.h> 60*2d1d418eSSumit Saxena #include <sys/queue.h> 61*2d1d418eSSumit Saxena #include <sys/kthread.h> 62*2d1d418eSSumit Saxena #include <sys/taskqueue.h> 63*2d1d418eSSumit Saxena #include <sys/sbuf.h> 64*2d1d418eSSumit Saxena 65*2d1d418eSSumit Saxena #include <machine/bus.h> 66*2d1d418eSSumit Saxena #include <machine/resource.h> 67*2d1d418eSSumit Saxena #include <sys/rman.h> 68*2d1d418eSSumit Saxena 69*2d1d418eSSumit Saxena #include <machine/stdarg.h> 70*2d1d418eSSumit Saxena 71*2d1d418eSSumit Saxena #include <cam/cam.h> 72*2d1d418eSSumit Saxena #include <cam/cam_ccb.h> 73*2d1d418eSSumit Saxena #include <cam/cam_debug.h> 74*2d1d418eSSumit Saxena #include <cam/cam_sim.h> 75*2d1d418eSSumit Saxena #include <cam/cam_xpt_sim.h> 76*2d1d418eSSumit Saxena #include <cam/cam_xpt_periph.h> 77*2d1d418eSSumit Saxena #include <cam/cam_periph.h> 78*2d1d418eSSumit Saxena #include <cam/scsi/scsi_all.h> 79*2d1d418eSSumit Saxena #include <cam/scsi/scsi_message.h> 80*2d1d418eSSumit Saxena #include <cam/scsi/smp_all.h> 81*2d1d418eSSumit Saxena 82*2d1d418eSSumit Saxena #include <dev/nvme/nvme.h> 83*2d1d418eSSumit Saxena #include "mpi/mpi30_api.h" 84*2d1d418eSSumit Saxena #include "mpi3mr_cam.h" 85*2d1d418eSSumit Saxena #include "mpi3mr.h" 86*2d1d418eSSumit Saxena #include <sys/time.h> /* XXX for pcpu.h */ 87*2d1d418eSSumit Saxena #include <sys/pcpu.h> /* XXX for PCPU_GET */ 88*2d1d418eSSumit Saxena 89*2d1d418eSSumit Saxena #define smp_processor_id() PCPU_GET(cpuid) 90*2d1d418eSSumit Saxena 91*2d1d418eSSumit Saxena static int 92*2d1d418eSSumit Saxena mpi3mr_map_request(struct mpi3mr_softc *sc, struct mpi3mr_cmd *cm); 93*2d1d418eSSumit Saxena void 94*2d1d418eSSumit Saxena mpi3mr_release_simq_reinit(struct mpi3mr_cam_softc *cam_sc); 95*2d1d418eSSumit Saxena static void 96*2d1d418eSSumit Saxena mpi3mr_freeup_events(struct mpi3mr_softc *sc); 97*2d1d418eSSumit Saxena 98*2d1d418eSSumit Saxena extern int 99*2d1d418eSSumit Saxena mpi3mr_register_events(struct mpi3mr_softc *sc); 100*2d1d418eSSumit Saxena extern void mpi3mr_add_sg_single(void *paddr, U8 flags, U32 length, 101*2d1d418eSSumit Saxena bus_addr_t dma_addr); 102*2d1d418eSSumit Saxena extern void mpi3mr_build_zero_len_sge(void *paddr); 103*2d1d418eSSumit Saxena 104*2d1d418eSSumit Saxena static U32 event_count; 105*2d1d418eSSumit Saxena 106*2d1d418eSSumit Saxena static void mpi3mr_prepare_sgls(void *arg, 107*2d1d418eSSumit Saxena bus_dma_segment_t *segs, int nsegs, int error) 108*2d1d418eSSumit Saxena { 109*2d1d418eSSumit Saxena struct mpi3mr_softc *sc; 110*2d1d418eSSumit Saxena struct mpi3mr_cmd *cm; 111*2d1d418eSSumit Saxena u_int i; 112*2d1d418eSSumit Saxena bus_addr_t chain_dma; 113*2d1d418eSSumit Saxena void *chain; 114*2d1d418eSSumit Saxena U8 *sg_local; 115*2d1d418eSSumit Saxena U32 chain_length; 116*2d1d418eSSumit Saxena int sges_left; 117*2d1d418eSSumit Saxena U32 sges_in_segment; 118*2d1d418eSSumit Saxena U8 simple_sgl_flags; 119*2d1d418eSSumit Saxena U8 simple_sgl_flags_last; 120*2d1d418eSSumit Saxena U8 last_chain_sgl_flags; 121*2d1d418eSSumit Saxena struct mpi3mr_chain *chain_req; 122*2d1d418eSSumit Saxena Mpi3SCSIIORequest_t *scsiio_req; 123*2d1d418eSSumit Saxena 124*2d1d418eSSumit Saxena cm = (struct mpi3mr_cmd *)arg; 125*2d1d418eSSumit Saxena sc = cm->sc; 126*2d1d418eSSumit Saxena scsiio_req = (Mpi3SCSIIORequest_t *) &cm->io_request; 127*2d1d418eSSumit Saxena 128*2d1d418eSSumit Saxena if (error) { 129*2d1d418eSSumit Saxena cm->error_code = error; 130*2d1d418eSSumit Saxena device_printf(sc->mpi3mr_dev, "%s: error=%d\n",__func__, error); 131*2d1d418eSSumit Saxena if (error == EFBIG) { 132*2d1d418eSSumit Saxena cm->ccb->ccb_h.status = CAM_REQ_TOO_BIG; 133*2d1d418eSSumit Saxena return; 134*2d1d418eSSumit Saxena } 135*2d1d418eSSumit Saxena } 136*2d1d418eSSumit Saxena 137*2d1d418eSSumit Saxena if (cm->data_dir == MPI3MR_READ) 138*2d1d418eSSumit Saxena bus_dmamap_sync(sc->buffer_dmat, cm->dmamap, 139*2d1d418eSSumit Saxena BUS_DMASYNC_PREREAD); 140*2d1d418eSSumit Saxena if (cm->data_dir == MPI3MR_WRITE) 141*2d1d418eSSumit Saxena bus_dmamap_sync(sc->buffer_dmat, cm->dmamap, 142*2d1d418eSSumit Saxena BUS_DMASYNC_PREWRITE); 143*2d1d418eSSumit Saxena if (nsegs > MPI3MR_SG_DEPTH) { 144*2d1d418eSSumit Saxena device_printf(sc->mpi3mr_dev, "SGE count is too large or 0.\n"); 145*2d1d418eSSumit Saxena return; 146*2d1d418eSSumit Saxena } 147*2d1d418eSSumit Saxena 148*2d1d418eSSumit Saxena simple_sgl_flags = MPI3_SGE_FLAGS_ELEMENT_TYPE_SIMPLE | 149*2d1d418eSSumit Saxena MPI3_SGE_FLAGS_DLAS_SYSTEM; 150*2d1d418eSSumit Saxena simple_sgl_flags_last = simple_sgl_flags | 151*2d1d418eSSumit Saxena MPI3_SGE_FLAGS_END_OF_LIST; 152*2d1d418eSSumit Saxena last_chain_sgl_flags = MPI3_SGE_FLAGS_ELEMENT_TYPE_LAST_CHAIN | 153*2d1d418eSSumit Saxena MPI3_SGE_FLAGS_DLAS_SYSTEM; 154*2d1d418eSSumit Saxena 155*2d1d418eSSumit Saxena sg_local = (U8 *)&scsiio_req->SGL; 156*2d1d418eSSumit Saxena 157*2d1d418eSSumit Saxena if (!scsiio_req->DataLength) { 158*2d1d418eSSumit Saxena mpi3mr_build_zero_len_sge(sg_local); 159*2d1d418eSSumit Saxena return; 160*2d1d418eSSumit Saxena } 161*2d1d418eSSumit Saxena 162*2d1d418eSSumit Saxena sges_left = nsegs; 163*2d1d418eSSumit Saxena 164*2d1d418eSSumit Saxena if (sges_left < 0) { 165*2d1d418eSSumit Saxena printf("scsi_dma_map failed: request for %d bytes!\n", 166*2d1d418eSSumit Saxena scsiio_req->DataLength); 167*2d1d418eSSumit Saxena return; 168*2d1d418eSSumit Saxena } 169*2d1d418eSSumit Saxena if (sges_left > MPI3MR_SG_DEPTH) { 170*2d1d418eSSumit Saxena printf("scsi_dma_map returned unsupported sge count %d!\n", 171*2d1d418eSSumit Saxena sges_left); 172*2d1d418eSSumit Saxena return; 173*2d1d418eSSumit Saxena } 174*2d1d418eSSumit Saxena 175*2d1d418eSSumit Saxena sges_in_segment = (sc->facts.op_req_sz - 176*2d1d418eSSumit Saxena offsetof(Mpi3SCSIIORequest_t, SGL))/sizeof(Mpi3SGESimple_t); 177*2d1d418eSSumit Saxena 178*2d1d418eSSumit Saxena i = 0; 179*2d1d418eSSumit Saxena 180*2d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_TRACE, "SGE count: %d IO size: %d\n", 181*2d1d418eSSumit Saxena nsegs, scsiio_req->DataLength); 182*2d1d418eSSumit Saxena 183*2d1d418eSSumit Saxena if (sges_left <= sges_in_segment) 184*2d1d418eSSumit Saxena goto fill_in_last_segment; 185*2d1d418eSSumit Saxena 186*2d1d418eSSumit Saxena /* fill in main message segment when there is a chain following */ 187*2d1d418eSSumit Saxena while (sges_in_segment > 1) { 188*2d1d418eSSumit Saxena mpi3mr_add_sg_single(sg_local, simple_sgl_flags, 189*2d1d418eSSumit Saxena segs[i].ds_len, segs[i].ds_addr); 190*2d1d418eSSumit Saxena sg_local += sizeof(Mpi3SGESimple_t); 191*2d1d418eSSumit Saxena sges_left--; 192*2d1d418eSSumit Saxena sges_in_segment--; 193*2d1d418eSSumit Saxena i++; 194*2d1d418eSSumit Saxena } 195*2d1d418eSSumit Saxena 196*2d1d418eSSumit Saxena chain_req = &sc->chain_sgl_list[cm->hosttag]; 197*2d1d418eSSumit Saxena 198*2d1d418eSSumit Saxena chain = chain_req->buf; 199*2d1d418eSSumit Saxena chain_dma = chain_req->buf_phys; 200*2d1d418eSSumit Saxena memset(chain_req->buf, 0, PAGE_SIZE); 201*2d1d418eSSumit Saxena sges_in_segment = sges_left; 202*2d1d418eSSumit Saxena chain_length = sges_in_segment * sizeof(Mpi3SGESimple_t); 203*2d1d418eSSumit Saxena 204*2d1d418eSSumit Saxena mpi3mr_add_sg_single(sg_local, last_chain_sgl_flags, 205*2d1d418eSSumit Saxena chain_length, chain_dma); 206*2d1d418eSSumit Saxena 207*2d1d418eSSumit Saxena sg_local = chain; 208*2d1d418eSSumit Saxena 209*2d1d418eSSumit Saxena fill_in_last_segment: 210*2d1d418eSSumit Saxena while (sges_left > 0) { 211*2d1d418eSSumit Saxena if (sges_left == 1) 212*2d1d418eSSumit Saxena mpi3mr_add_sg_single(sg_local, 213*2d1d418eSSumit Saxena simple_sgl_flags_last, segs[i].ds_len, 214*2d1d418eSSumit Saxena segs[i].ds_addr); 215*2d1d418eSSumit Saxena else 216*2d1d418eSSumit Saxena mpi3mr_add_sg_single(sg_local, simple_sgl_flags, 217*2d1d418eSSumit Saxena segs[i].ds_len, segs[i].ds_addr); 218*2d1d418eSSumit Saxena sg_local += sizeof(Mpi3SGESimple_t); 219*2d1d418eSSumit Saxena sges_left--; 220*2d1d418eSSumit Saxena i++; 221*2d1d418eSSumit Saxena } 222*2d1d418eSSumit Saxena 223*2d1d418eSSumit Saxena return; 224*2d1d418eSSumit Saxena } 225*2d1d418eSSumit Saxena 226*2d1d418eSSumit Saxena int 227*2d1d418eSSumit Saxena mpi3mr_map_request(struct mpi3mr_softc *sc, struct mpi3mr_cmd *cm) 228*2d1d418eSSumit Saxena { 229*2d1d418eSSumit Saxena u_int32_t retcode = 0; 230*2d1d418eSSumit Saxena 231*2d1d418eSSumit Saxena if (cm->data != NULL) { 232*2d1d418eSSumit Saxena mtx_lock(&sc->io_lock); 233*2d1d418eSSumit Saxena /* Map data buffer into bus space */ 234*2d1d418eSSumit Saxena retcode = bus_dmamap_load_ccb(sc->buffer_dmat, cm->dmamap, 235*2d1d418eSSumit Saxena cm->ccb, mpi3mr_prepare_sgls, cm, 0); 236*2d1d418eSSumit Saxena mtx_unlock(&sc->io_lock); 237*2d1d418eSSumit Saxena if (retcode) 238*2d1d418eSSumit Saxena device_printf(sc->mpi3mr_dev, "bus_dmamap_load(): retcode = %d\n", retcode); 239*2d1d418eSSumit Saxena if (retcode == EINPROGRESS) { 240*2d1d418eSSumit Saxena device_printf(sc->mpi3mr_dev, "request load in progress\n"); 241*2d1d418eSSumit Saxena xpt_freeze_simq(sc->cam_sc->sim, 1); 242*2d1d418eSSumit Saxena } 243*2d1d418eSSumit Saxena } 244*2d1d418eSSumit Saxena if (cm->error_code) 245*2d1d418eSSumit Saxena return cm->error_code; 246*2d1d418eSSumit Saxena if (retcode) 247*2d1d418eSSumit Saxena mpi3mr_set_ccbstatus(cm->ccb, CAM_REQ_INVALID); 248*2d1d418eSSumit Saxena 249*2d1d418eSSumit Saxena return (retcode); 250*2d1d418eSSumit Saxena } 251*2d1d418eSSumit Saxena 252*2d1d418eSSumit Saxena void 253*2d1d418eSSumit Saxena mpi3mr_unmap_request(struct mpi3mr_softc *sc, struct mpi3mr_cmd *cmd) 254*2d1d418eSSumit Saxena { 255*2d1d418eSSumit Saxena if (cmd->data != NULL) { 256*2d1d418eSSumit Saxena if (cmd->data_dir == MPI3MR_READ) 257*2d1d418eSSumit Saxena bus_dmamap_sync(sc->buffer_dmat, cmd->dmamap, BUS_DMASYNC_POSTREAD); 258*2d1d418eSSumit Saxena if (cmd->data_dir == MPI3MR_WRITE) 259*2d1d418eSSumit Saxena bus_dmamap_sync(sc->buffer_dmat, cmd->dmamap, BUS_DMASYNC_POSTWRITE); 260*2d1d418eSSumit Saxena mtx_lock(&sc->io_lock); 261*2d1d418eSSumit Saxena bus_dmamap_unload(sc->buffer_dmat, cmd->dmamap); 262*2d1d418eSSumit Saxena mtx_unlock(&sc->io_lock); 263*2d1d418eSSumit Saxena } 264*2d1d418eSSumit Saxena } 265*2d1d418eSSumit Saxena 266*2d1d418eSSumit Saxena /** 267*2d1d418eSSumit Saxena * mpi3mr_allow_unmap_to_fw - Whether an unmap is allowed to fw 268*2d1d418eSSumit Saxena * @sc: Adapter instance reference 269*2d1d418eSSumit Saxena * @ccb: SCSI Command reference 270*2d1d418eSSumit Saxena * 271*2d1d418eSSumit Saxena * The controller hardware cannot handle certain unmap commands 272*2d1d418eSSumit Saxena * for NVMe drives, this routine checks those and return true 273*2d1d418eSSumit Saxena * and completes the SCSI command with proper status and sense 274*2d1d418eSSumit Saxena * data. 275*2d1d418eSSumit Saxena * 276*2d1d418eSSumit Saxena * Return: TRUE for allowed unmap, FALSE otherwise. 277*2d1d418eSSumit Saxena */ 278*2d1d418eSSumit Saxena static bool mpi3mr_allow_unmap_to_fw(struct mpi3mr_softc *sc, 279*2d1d418eSSumit Saxena union ccb *ccb) 280*2d1d418eSSumit Saxena { 281*2d1d418eSSumit Saxena struct ccb_scsiio *csio; 282*2d1d418eSSumit Saxena uint16_t param_list_len, block_desc_len, trunc_param_len = 0; 283*2d1d418eSSumit Saxena 284*2d1d418eSSumit Saxena csio = &ccb->csio; 285*2d1d418eSSumit Saxena param_list_len = (uint16_t) ((scsiio_cdb_ptr(csio)[7] << 8) | scsiio_cdb_ptr(csio)[8]); 286*2d1d418eSSumit Saxena 287*2d1d418eSSumit Saxena switch(pci_get_revid(sc->mpi3mr_dev)) { 288*2d1d418eSSumit Saxena case SAS4116_CHIP_REV_A0: 289*2d1d418eSSumit Saxena if (!param_list_len) { 290*2d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_ERROR, 291*2d1d418eSSumit Saxena "%s: CDB received with zero parameter length\n", 292*2d1d418eSSumit Saxena __func__); 293*2d1d418eSSumit Saxena mpi3mr_print_cdb(ccb); 294*2d1d418eSSumit Saxena mpi3mr_set_ccbstatus(ccb, CAM_REQ_CMP); 295*2d1d418eSSumit Saxena xpt_done(ccb); 296*2d1d418eSSumit Saxena return false; 297*2d1d418eSSumit Saxena } 298*2d1d418eSSumit Saxena 299*2d1d418eSSumit Saxena if (param_list_len < 24) { 300*2d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_ERROR, 301*2d1d418eSSumit Saxena "%s: CDB received with invalid param_list_len: %d\n", 302*2d1d418eSSumit Saxena __func__, param_list_len); 303*2d1d418eSSumit Saxena mpi3mr_print_cdb(ccb); 304*2d1d418eSSumit Saxena scsi_set_sense_data(&ccb->csio.sense_data, 305*2d1d418eSSumit Saxena /*sense_format*/ SSD_TYPE_FIXED, 306*2d1d418eSSumit Saxena /*current_error*/ 1, 307*2d1d418eSSumit Saxena /*sense_key*/ SSD_KEY_ILLEGAL_REQUEST, 308*2d1d418eSSumit Saxena /*asc*/ 0x1A, 309*2d1d418eSSumit Saxena /*ascq*/ 0x00, 310*2d1d418eSSumit Saxena /*extra args*/ SSD_ELEM_NONE); 311*2d1d418eSSumit Saxena ccb->csio.scsi_status = SCSI_STATUS_CHECK_COND; 312*2d1d418eSSumit Saxena ccb->ccb_h.status = 313*2d1d418eSSumit Saxena CAM_SCSI_STATUS_ERROR | 314*2d1d418eSSumit Saxena CAM_AUTOSNS_VALID; 315*2d1d418eSSumit Saxena return false; 316*2d1d418eSSumit Saxena } 317*2d1d418eSSumit Saxena 318*2d1d418eSSumit Saxena if (param_list_len != csio->dxfer_len) { 319*2d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_ERROR, 320*2d1d418eSSumit Saxena "%s: CDB received with param_list_len: %d bufflen: %d\n", 321*2d1d418eSSumit Saxena __func__, param_list_len, csio->dxfer_len); 322*2d1d418eSSumit Saxena mpi3mr_print_cdb(ccb); 323*2d1d418eSSumit Saxena scsi_set_sense_data(&ccb->csio.sense_data, 324*2d1d418eSSumit Saxena /*sense_format*/ SSD_TYPE_FIXED, 325*2d1d418eSSumit Saxena /*current_error*/ 1, 326*2d1d418eSSumit Saxena /*sense_key*/ SSD_KEY_ILLEGAL_REQUEST, 327*2d1d418eSSumit Saxena /*asc*/ 0x1A, 328*2d1d418eSSumit Saxena /*ascq*/ 0x00, 329*2d1d418eSSumit Saxena /*extra args*/ SSD_ELEM_NONE); 330*2d1d418eSSumit Saxena ccb->csio.scsi_status = SCSI_STATUS_CHECK_COND; 331*2d1d418eSSumit Saxena ccb->ccb_h.status = 332*2d1d418eSSumit Saxena CAM_SCSI_STATUS_ERROR | 333*2d1d418eSSumit Saxena CAM_AUTOSNS_VALID; 334*2d1d418eSSumit Saxena xpt_done(ccb); 335*2d1d418eSSumit Saxena return false; 336*2d1d418eSSumit Saxena } 337*2d1d418eSSumit Saxena 338*2d1d418eSSumit Saxena block_desc_len = (uint16_t) (csio->data_ptr[2] << 8 | csio->data_ptr[3]); 339*2d1d418eSSumit Saxena 340*2d1d418eSSumit Saxena if (block_desc_len < 16) { 341*2d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_ERROR, 342*2d1d418eSSumit Saxena "%s: Invalid descriptor length in param list: %d\n", 343*2d1d418eSSumit Saxena __func__, block_desc_len); 344*2d1d418eSSumit Saxena mpi3mr_print_cdb(ccb); 345*2d1d418eSSumit Saxena scsi_set_sense_data(&ccb->csio.sense_data, 346*2d1d418eSSumit Saxena /*sense_format*/ SSD_TYPE_FIXED, 347*2d1d418eSSumit Saxena /*current_error*/ 1, 348*2d1d418eSSumit Saxena /*sense_key*/ SSD_KEY_ILLEGAL_REQUEST, 349*2d1d418eSSumit Saxena /*asc*/ 0x26, 350*2d1d418eSSumit Saxena /*ascq*/ 0x00, 351*2d1d418eSSumit Saxena /*extra args*/ SSD_ELEM_NONE); 352*2d1d418eSSumit Saxena ccb->csio.scsi_status = SCSI_STATUS_CHECK_COND; 353*2d1d418eSSumit Saxena ccb->ccb_h.status = 354*2d1d418eSSumit Saxena CAM_SCSI_STATUS_ERROR | 355*2d1d418eSSumit Saxena CAM_AUTOSNS_VALID; 356*2d1d418eSSumit Saxena xpt_done(ccb); 357*2d1d418eSSumit Saxena return false; 358*2d1d418eSSumit Saxena } 359*2d1d418eSSumit Saxena 360*2d1d418eSSumit Saxena if (param_list_len > (block_desc_len + 8)) { 361*2d1d418eSSumit Saxena mpi3mr_print_cdb(ccb); 362*2d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_INFO, 363*2d1d418eSSumit Saxena "%s: Truncating param_list_len(%d) to block_desc_len+8(%d)\n", 364*2d1d418eSSumit Saxena __func__, param_list_len, (block_desc_len + 8)); 365*2d1d418eSSumit Saxena param_list_len = block_desc_len + 8; 366*2d1d418eSSumit Saxena scsiio_cdb_ptr(csio)[7] = (param_list_len >> 8) | 0xff; 367*2d1d418eSSumit Saxena scsiio_cdb_ptr(csio)[8] = param_list_len | 0xff; 368*2d1d418eSSumit Saxena mpi3mr_print_cdb(ccb); 369*2d1d418eSSumit Saxena } 370*2d1d418eSSumit Saxena break; 371*2d1d418eSSumit Saxena 372*2d1d418eSSumit Saxena case SAS4116_CHIP_REV_B0: 373*2d1d418eSSumit Saxena if ((param_list_len > 24) && ((param_list_len - 8) & 0xF)) { 374*2d1d418eSSumit Saxena trunc_param_len -= (param_list_len - 8) & 0xF; 375*2d1d418eSSumit Saxena mpi3mr_print_cdb(ccb); 376*2d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_INFO, 377*2d1d418eSSumit Saxena "%s: Truncating param_list_len from (%d) to (%d)\n", 378*2d1d418eSSumit Saxena __func__, param_list_len, trunc_param_len); 379*2d1d418eSSumit Saxena scsiio_cdb_ptr(csio)[7] = (param_list_len >> 8) | 0xff; 380*2d1d418eSSumit Saxena scsiio_cdb_ptr(csio)[8] = param_list_len | 0xff; 381*2d1d418eSSumit Saxena mpi3mr_print_cdb(ccb); 382*2d1d418eSSumit Saxena } 383*2d1d418eSSumit Saxena break; 384*2d1d418eSSumit Saxena } 385*2d1d418eSSumit Saxena 386*2d1d418eSSumit Saxena return true; 387*2d1d418eSSumit Saxena } 388*2d1d418eSSumit Saxena 389*2d1d418eSSumit Saxena /** 390*2d1d418eSSumit Saxena * mpi3mr_tm_response_name - get TM response as a string 391*2d1d418eSSumit Saxena * @resp_code: TM response code 392*2d1d418eSSumit Saxena * 393*2d1d418eSSumit Saxena * Convert known task management response code as a readable 394*2d1d418eSSumit Saxena * string. 395*2d1d418eSSumit Saxena * 396*2d1d418eSSumit Saxena * Return: response code string. 397*2d1d418eSSumit Saxena */ 398*2d1d418eSSumit Saxena static const char* mpi3mr_tm_response_name(U8 resp_code) 399*2d1d418eSSumit Saxena { 400*2d1d418eSSumit Saxena char *desc; 401*2d1d418eSSumit Saxena 402*2d1d418eSSumit Saxena switch (resp_code) { 403*2d1d418eSSumit Saxena case MPI3_SCSITASKMGMT_RSPCODE_TM_COMPLETE: 404*2d1d418eSSumit Saxena desc = "task management request completed"; 405*2d1d418eSSumit Saxena break; 406*2d1d418eSSumit Saxena case MPI3_SCSITASKMGMT_RSPCODE_INVALID_FRAME: 407*2d1d418eSSumit Saxena desc = "invalid frame"; 408*2d1d418eSSumit Saxena break; 409*2d1d418eSSumit Saxena case MPI3_SCSITASKMGMT_RSPCODE_TM_FUNCTION_NOT_SUPPORTED: 410*2d1d418eSSumit Saxena desc = "task management request not supported"; 411*2d1d418eSSumit Saxena break; 412*2d1d418eSSumit Saxena case MPI3_SCSITASKMGMT_RSPCODE_TM_FAILED: 413*2d1d418eSSumit Saxena desc = "task management request failed"; 414*2d1d418eSSumit Saxena break; 415*2d1d418eSSumit Saxena case MPI3_SCSITASKMGMT_RSPCODE_TM_SUCCEEDED: 416*2d1d418eSSumit Saxena desc = "task management request succeeded"; 417*2d1d418eSSumit Saxena break; 418*2d1d418eSSumit Saxena case MPI3_SCSITASKMGMT_RSPCODE_TM_INVALID_LUN: 419*2d1d418eSSumit Saxena desc = "invalid LUN"; 420*2d1d418eSSumit Saxena break; 421*2d1d418eSSumit Saxena case MPI3_SCSITASKMGMT_RSPCODE_TM_OVERLAPPED_TAG: 422*2d1d418eSSumit Saxena desc = "overlapped tag attempted"; 423*2d1d418eSSumit Saxena break; 424*2d1d418eSSumit Saxena case MPI3_SCSITASKMGMT_RSPCODE_IO_QUEUED_ON_IOC: 425*2d1d418eSSumit Saxena desc = "task queued, however not sent to target"; 426*2d1d418eSSumit Saxena break; 427*2d1d418eSSumit Saxena case MPI3_SCSITASKMGMT_RSPCODE_TM_NVME_DENIED: 428*2d1d418eSSumit Saxena desc = "task management request denied by NVMe device"; 429*2d1d418eSSumit Saxena break; 430*2d1d418eSSumit Saxena default: 431*2d1d418eSSumit Saxena desc = "unknown"; 432*2d1d418eSSumit Saxena break; 433*2d1d418eSSumit Saxena } 434*2d1d418eSSumit Saxena 435*2d1d418eSSumit Saxena return desc; 436*2d1d418eSSumit Saxena } 437*2d1d418eSSumit Saxena 438*2d1d418eSSumit Saxena void mpi3mr_poll_pend_io_completions(struct mpi3mr_softc *sc) 439*2d1d418eSSumit Saxena { 440*2d1d418eSSumit Saxena int i; 441*2d1d418eSSumit Saxena int num_of_reply_queues = sc->num_queues; 442*2d1d418eSSumit Saxena struct mpi3mr_irq_context *irq_ctx; 443*2d1d418eSSumit Saxena 444*2d1d418eSSumit Saxena for (i = 0; i < num_of_reply_queues; i++) { 445*2d1d418eSSumit Saxena irq_ctx = &sc->irq_ctx[i]; 446*2d1d418eSSumit Saxena mpi3mr_complete_io_cmd(sc, irq_ctx); 447*2d1d418eSSumit Saxena } 448*2d1d418eSSumit Saxena } 449*2d1d418eSSumit Saxena 450*2d1d418eSSumit Saxena void 451*2d1d418eSSumit Saxena trigger_reset_from_watchdog(struct mpi3mr_softc *sc, U8 reset_type, U32 reset_reason) 452*2d1d418eSSumit Saxena { 453*2d1d418eSSumit Saxena if (sc->reset_in_progress) { 454*2d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_INFO, "Another reset is in progress, no need to trigger the reset\n"); 455*2d1d418eSSumit Saxena return; 456*2d1d418eSSumit Saxena } 457*2d1d418eSSumit Saxena sc->reset.type = reset_type; 458*2d1d418eSSumit Saxena sc->reset.reason = reset_reason; 459*2d1d418eSSumit Saxena 460*2d1d418eSSumit Saxena return; 461*2d1d418eSSumit Saxena } 462*2d1d418eSSumit Saxena 463*2d1d418eSSumit Saxena /** 464*2d1d418eSSumit Saxena * mpi3mr_issue_tm - Issue Task Management request 465*2d1d418eSSumit Saxena * @sc: Adapter instance reference 466*2d1d418eSSumit Saxena * @tm_type: Task Management type 467*2d1d418eSSumit Saxena * @handle: Device handle 468*2d1d418eSSumit Saxena * @lun: lun ID 469*2d1d418eSSumit Saxena * @htag: Host tag of the TM request 470*2d1d418eSSumit Saxena * @timeout: TM timeout value 471*2d1d418eSSumit Saxena * @drv_cmd: Internal command tracker 472*2d1d418eSSumit Saxena * @resp_code: Response code place holder 473*2d1d418eSSumit Saxena * @cmd: Timed out command reference 474*2d1d418eSSumit Saxena * 475*2d1d418eSSumit Saxena * Issues a Task Management Request to the controller for a 476*2d1d418eSSumit Saxena * specified target, lun and command and wait for its completion 477*2d1d418eSSumit Saxena * and check TM response. Recover the TM if it timed out by 478*2d1d418eSSumit Saxena * issuing controller reset. 479*2d1d418eSSumit Saxena * 480*2d1d418eSSumit Saxena * Return: 0 on success, non-zero on errors 481*2d1d418eSSumit Saxena */ 482*2d1d418eSSumit Saxena static int 483*2d1d418eSSumit Saxena mpi3mr_issue_tm(struct mpi3mr_softc *sc, struct mpi3mr_cmd *cmd, 484*2d1d418eSSumit Saxena U8 tm_type, unsigned long timeout) 485*2d1d418eSSumit Saxena { 486*2d1d418eSSumit Saxena int retval = 0; 487*2d1d418eSSumit Saxena MPI3_SCSI_TASK_MGMT_REQUEST tm_req; 488*2d1d418eSSumit Saxena MPI3_SCSI_TASK_MGMT_REPLY *tm_reply = NULL; 489*2d1d418eSSumit Saxena struct mpi3mr_drvr_cmd *drv_cmd = NULL; 490*2d1d418eSSumit Saxena struct mpi3mr_target *tgtdev = NULL; 491*2d1d418eSSumit Saxena struct mpi3mr_op_req_queue *op_req_q = NULL; 492*2d1d418eSSumit Saxena union ccb *ccb; 493*2d1d418eSSumit Saxena U8 resp_code; 494*2d1d418eSSumit Saxena 495*2d1d418eSSumit Saxena 496*2d1d418eSSumit Saxena if (sc->unrecoverable) { 497*2d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_INFO, 498*2d1d418eSSumit Saxena "Controller is in unrecoverable state!! TM not required\n"); 499*2d1d418eSSumit Saxena return retval; 500*2d1d418eSSumit Saxena } 501*2d1d418eSSumit Saxena if (sc->reset_in_progress) { 502*2d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_INFO, 503*2d1d418eSSumit Saxena "controller reset in progress!! TM not required\n"); 504*2d1d418eSSumit Saxena return retval; 505*2d1d418eSSumit Saxena } 506*2d1d418eSSumit Saxena 507*2d1d418eSSumit Saxena if (!cmd->ccb) { 508*2d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_ERROR, "SCSIIO command timed-out with NULL ccb\n"); 509*2d1d418eSSumit Saxena return retval; 510*2d1d418eSSumit Saxena } 511*2d1d418eSSumit Saxena ccb = cmd->ccb; 512*2d1d418eSSumit Saxena 513*2d1d418eSSumit Saxena tgtdev = cmd->targ; 514*2d1d418eSSumit Saxena if (tgtdev == NULL) { 515*2d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_ERROR, "Device does not exist target ID:0x%x," 516*2d1d418eSSumit Saxena "TM is not required\n", ccb->ccb_h.target_id); 517*2d1d418eSSumit Saxena return retval; 518*2d1d418eSSumit Saxena } 519*2d1d418eSSumit Saxena if (tgtdev->dev_removed == 1) { 520*2d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_ERROR, "Device(0x%x) is removed, TM is not required\n", 521*2d1d418eSSumit Saxena ccb->ccb_h.target_id); 522*2d1d418eSSumit Saxena return retval; 523*2d1d418eSSumit Saxena } 524*2d1d418eSSumit Saxena 525*2d1d418eSSumit Saxena drv_cmd = &sc->host_tm_cmds; 526*2d1d418eSSumit Saxena mtx_lock(&drv_cmd->lock); 527*2d1d418eSSumit Saxena 528*2d1d418eSSumit Saxena memset(&tm_req, 0, sizeof(tm_req)); 529*2d1d418eSSumit Saxena tm_req.DevHandle = htole16(tgtdev->dev_handle); 530*2d1d418eSSumit Saxena tm_req.TaskType = tm_type; 531*2d1d418eSSumit Saxena tm_req.HostTag = htole16(MPI3MR_HOSTTAG_TMS); 532*2d1d418eSSumit Saxena int_to_lun(ccb->ccb_h.target_lun, tm_req.LUN); 533*2d1d418eSSumit Saxena tm_req.Function = MPI3_FUNCTION_SCSI_TASK_MGMT; 534*2d1d418eSSumit Saxena drv_cmd->state = MPI3MR_CMD_PENDING; 535*2d1d418eSSumit Saxena drv_cmd->is_waiting = 1; 536*2d1d418eSSumit Saxena drv_cmd->callback = NULL; 537*2d1d418eSSumit Saxena 538*2d1d418eSSumit Saxena if (ccb) { 539*2d1d418eSSumit Saxena if (tm_type == MPI3_SCSITASKMGMT_TASKTYPE_ABORT_TASK) { 540*2d1d418eSSumit Saxena op_req_q = &sc->op_req_q[cmd->req_qidx]; 541*2d1d418eSSumit Saxena tm_req.TaskHostTag = htole16(cmd->hosttag); 542*2d1d418eSSumit Saxena tm_req.TaskRequestQueueID = htole16(op_req_q->qid); 543*2d1d418eSSumit Saxena } 544*2d1d418eSSumit Saxena } 545*2d1d418eSSumit Saxena 546*2d1d418eSSumit Saxena if (tgtdev) 547*2d1d418eSSumit Saxena mpi3mr_atomic_inc(&tgtdev->block_io); 548*2d1d418eSSumit Saxena 549*2d1d418eSSumit Saxena if (tgtdev && (tgtdev->dev_type == MPI3_DEVICE_DEVFORM_PCIE)) { 550*2d1d418eSSumit Saxena if ((tm_type == MPI3_SCSITASKMGMT_TASKTYPE_ABORT_TASK) 551*2d1d418eSSumit Saxena && tgtdev->dev_spec.pcie_inf.abort_to) 552*2d1d418eSSumit Saxena timeout = tgtdev->dev_spec.pcie_inf.abort_to; 553*2d1d418eSSumit Saxena else if ((tm_type == MPI3_SCSITASKMGMT_TASKTYPE_TARGET_RESET) 554*2d1d418eSSumit Saxena && tgtdev->dev_spec.pcie_inf.reset_to) 555*2d1d418eSSumit Saxena timeout = tgtdev->dev_spec.pcie_inf.reset_to; 556*2d1d418eSSumit Saxena } 557*2d1d418eSSumit Saxena 558*2d1d418eSSumit Saxena sc->tm_chan = (void *)&drv_cmd; 559*2d1d418eSSumit Saxena 560*2d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_DEBUG_TM, 561*2d1d418eSSumit Saxena "posting task management request: type(%d), handle(0x%04x)\n", 562*2d1d418eSSumit Saxena tm_type, tgtdev->dev_handle); 563*2d1d418eSSumit Saxena 564*2d1d418eSSumit Saxena init_completion(&drv_cmd->completion); 565*2d1d418eSSumit Saxena retval = mpi3mr_submit_admin_cmd(sc, &tm_req, sizeof(tm_req)); 566*2d1d418eSSumit Saxena if (retval) { 567*2d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_ERROR, 568*2d1d418eSSumit Saxena "posting task management request is failed\n"); 569*2d1d418eSSumit Saxena retval = -1; 570*2d1d418eSSumit Saxena goto out_unlock; 571*2d1d418eSSumit Saxena } 572*2d1d418eSSumit Saxena wait_for_completion_timeout_tm(&drv_cmd->completion, timeout, sc); 573*2d1d418eSSumit Saxena 574*2d1d418eSSumit Saxena if (!(drv_cmd->state & MPI3MR_CMD_COMPLETE)) { 575*2d1d418eSSumit Saxena drv_cmd->is_waiting = 0; 576*2d1d418eSSumit Saxena retval = -1; 577*2d1d418eSSumit Saxena if (!(drv_cmd->state & MPI3MR_CMD_RESET)) { 578*2d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_ERROR, 579*2d1d418eSSumit Saxena "task management request timed out after %ld seconds\n", timeout); 580*2d1d418eSSumit Saxena if (sc->mpi3mr_debug & MPI3MR_DEBUG_TM) { 581*2d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_INFO, "tm_request dump\n"); 582*2d1d418eSSumit Saxena mpi3mr_hexdump(&tm_req, sizeof(tm_req), 8); 583*2d1d418eSSumit Saxena } 584*2d1d418eSSumit Saxena trigger_reset_from_watchdog(sc, MPI3MR_TRIGGER_SOFT_RESET, MPI3MR_RESET_FROM_TM_TIMEOUT); 585*2d1d418eSSumit Saxena retval = ETIMEDOUT; 586*2d1d418eSSumit Saxena } 587*2d1d418eSSumit Saxena goto out_unlock; 588*2d1d418eSSumit Saxena } 589*2d1d418eSSumit Saxena 590*2d1d418eSSumit Saxena if (!(drv_cmd->state & MPI3MR_CMD_REPLYVALID)) { 591*2d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_ERROR, 592*2d1d418eSSumit Saxena "invalid task management reply message\n"); 593*2d1d418eSSumit Saxena retval = -1; 594*2d1d418eSSumit Saxena goto out_unlock; 595*2d1d418eSSumit Saxena } 596*2d1d418eSSumit Saxena tm_reply = (MPI3_SCSI_TASK_MGMT_REPLY *)drv_cmd->reply; 597*2d1d418eSSumit Saxena 598*2d1d418eSSumit Saxena switch (drv_cmd->ioc_status) { 599*2d1d418eSSumit Saxena case MPI3_IOCSTATUS_SUCCESS: 600*2d1d418eSSumit Saxena resp_code = tm_reply->ResponseData & MPI3MR_RI_MASK_RESPCODE; 601*2d1d418eSSumit Saxena break; 602*2d1d418eSSumit Saxena case MPI3_IOCSTATUS_SCSI_IOC_TERMINATED: 603*2d1d418eSSumit Saxena resp_code = MPI3_SCSITASKMGMT_RSPCODE_TM_COMPLETE; 604*2d1d418eSSumit Saxena break; 605*2d1d418eSSumit Saxena default: 606*2d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_ERROR, 607*2d1d418eSSumit Saxena "task management request to handle(0x%04x) is failed with ioc_status(0x%04x) log_info(0x%08x)\n", 608*2d1d418eSSumit Saxena tgtdev->dev_handle, drv_cmd->ioc_status, drv_cmd->ioc_loginfo); 609*2d1d418eSSumit Saxena retval = -1; 610*2d1d418eSSumit Saxena goto out_unlock; 611*2d1d418eSSumit Saxena } 612*2d1d418eSSumit Saxena 613*2d1d418eSSumit Saxena switch (resp_code) { 614*2d1d418eSSumit Saxena case MPI3_SCSITASKMGMT_RSPCODE_TM_SUCCEEDED: 615*2d1d418eSSumit Saxena case MPI3_SCSITASKMGMT_RSPCODE_TM_COMPLETE: 616*2d1d418eSSumit Saxena break; 617*2d1d418eSSumit Saxena case MPI3_SCSITASKMGMT_RSPCODE_IO_QUEUED_ON_IOC: 618*2d1d418eSSumit Saxena if (tm_type != MPI3_SCSITASKMGMT_TASKTYPE_QUERY_TASK) 619*2d1d418eSSumit Saxena retval = -1; 620*2d1d418eSSumit Saxena break; 621*2d1d418eSSumit Saxena default: 622*2d1d418eSSumit Saxena retval = -1; 623*2d1d418eSSumit Saxena break; 624*2d1d418eSSumit Saxena } 625*2d1d418eSSumit Saxena 626*2d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_DEBUG_TM, 627*2d1d418eSSumit Saxena "task management request type(%d) completed for handle(0x%04x) with ioc_status(0x%04x), log_info(0x%08x)" 628*2d1d418eSSumit Saxena "termination_count(%u), response:%s(0x%x)\n", tm_type, tgtdev->dev_handle, drv_cmd->ioc_status, drv_cmd->ioc_loginfo, 629*2d1d418eSSumit Saxena tm_reply->TerminationCount, mpi3mr_tm_response_name(resp_code), resp_code); 630*2d1d418eSSumit Saxena 631*2d1d418eSSumit Saxena if (retval) 632*2d1d418eSSumit Saxena goto out_unlock; 633*2d1d418eSSumit Saxena 634*2d1d418eSSumit Saxena mpi3mr_disable_interrupts(sc); 635*2d1d418eSSumit Saxena mpi3mr_poll_pend_io_completions(sc); 636*2d1d418eSSumit Saxena mpi3mr_enable_interrupts(sc); 637*2d1d418eSSumit Saxena mpi3mr_poll_pend_io_completions(sc); 638*2d1d418eSSumit Saxena 639*2d1d418eSSumit Saxena switch (tm_type) { 640*2d1d418eSSumit Saxena case MPI3_SCSITASKMGMT_TASKTYPE_ABORT_TASK: 641*2d1d418eSSumit Saxena if (cmd->state == MPI3MR_CMD_STATE_IN_TM) { 642*2d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_ERROR, 643*2d1d418eSSumit Saxena "%s: task abort returned success from firmware but corresponding CCB (%p) was not terminated" 644*2d1d418eSSumit Saxena "marking task abort failed!\n", sc->name, cmd->ccb); 645*2d1d418eSSumit Saxena retval = -1; 646*2d1d418eSSumit Saxena } 647*2d1d418eSSumit Saxena break; 648*2d1d418eSSumit Saxena case MPI3_SCSITASKMGMT_TASKTYPE_TARGET_RESET: 649*2d1d418eSSumit Saxena if (mpi3mr_atomic_read(&tgtdev->outstanding)) { 650*2d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_ERROR, 651*2d1d418eSSumit Saxena "%s: target reset returned success from firmware but IOs are still pending on the target (%p)" 652*2d1d418eSSumit Saxena "marking target reset failed!\n", 653*2d1d418eSSumit Saxena sc->name, tgtdev); 654*2d1d418eSSumit Saxena retval = -1; 655*2d1d418eSSumit Saxena } 656*2d1d418eSSumit Saxena break; 657*2d1d418eSSumit Saxena default: 658*2d1d418eSSumit Saxena break; 659*2d1d418eSSumit Saxena } 660*2d1d418eSSumit Saxena 661*2d1d418eSSumit Saxena out_unlock: 662*2d1d418eSSumit Saxena drv_cmd->state = MPI3MR_CMD_NOTUSED; 663*2d1d418eSSumit Saxena mtx_unlock(&drv_cmd->lock); 664*2d1d418eSSumit Saxena if (tgtdev && mpi3mr_atomic_read(&tgtdev->block_io) > 0) 665*2d1d418eSSumit Saxena mpi3mr_atomic_dec(&tgtdev->block_io); 666*2d1d418eSSumit Saxena 667*2d1d418eSSumit Saxena return retval; 668*2d1d418eSSumit Saxena } 669*2d1d418eSSumit Saxena 670*2d1d418eSSumit Saxena /** 671*2d1d418eSSumit Saxena * mpi3mr_task_abort- Abort error handling callback 672*2d1d418eSSumit Saxena * @cmd: Timed out command reference 673*2d1d418eSSumit Saxena * 674*2d1d418eSSumit Saxena * Issue Abort Task Management if the command is in LLD scope 675*2d1d418eSSumit Saxena * and verify if it is aborted successfully and return status 676*2d1d418eSSumit Saxena * accordingly. 677*2d1d418eSSumit Saxena * 678*2d1d418eSSumit Saxena * Return: SUCCESS of successful abort the SCSI command else FAILED 679*2d1d418eSSumit Saxena */ 680*2d1d418eSSumit Saxena static int mpi3mr_task_abort(struct mpi3mr_cmd *cmd) 681*2d1d418eSSumit Saxena { 682*2d1d418eSSumit Saxena int retval = 0; 683*2d1d418eSSumit Saxena struct mpi3mr_softc *sc; 684*2d1d418eSSumit Saxena union ccb *ccb; 685*2d1d418eSSumit Saxena 686*2d1d418eSSumit Saxena sc = cmd->sc; 687*2d1d418eSSumit Saxena 688*2d1d418eSSumit Saxena if (!cmd->ccb) { 689*2d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_ERROR, "SCSIIO command timed-out with NULL ccb\n"); 690*2d1d418eSSumit Saxena return retval; 691*2d1d418eSSumit Saxena } 692*2d1d418eSSumit Saxena ccb = cmd->ccb; 693*2d1d418eSSumit Saxena 694*2d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_INFO, 695*2d1d418eSSumit Saxena "attempting abort task for ccb(%p)\n", ccb); 696*2d1d418eSSumit Saxena 697*2d1d418eSSumit Saxena mpi3mr_print_cdb(ccb); 698*2d1d418eSSumit Saxena 699*2d1d418eSSumit Saxena if (cmd->state != MPI3MR_CMD_STATE_BUSY) { 700*2d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_INFO, 701*2d1d418eSSumit Saxena "%s: ccb is not in driver scope, abort task is not required\n", 702*2d1d418eSSumit Saxena sc->name); 703*2d1d418eSSumit Saxena return retval; 704*2d1d418eSSumit Saxena } 705*2d1d418eSSumit Saxena cmd->state = MPI3MR_CMD_STATE_IN_TM; 706*2d1d418eSSumit Saxena 707*2d1d418eSSumit Saxena retval = mpi3mr_issue_tm(sc, cmd, MPI3_SCSITASKMGMT_TASKTYPE_ABORT_TASK, MPI3MR_ABORTTM_TIMEOUT); 708*2d1d418eSSumit Saxena 709*2d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_INFO, 710*2d1d418eSSumit Saxena "abort task is %s for ccb(%p)\n", ((retval == 0) ? "SUCCESS" : "FAILED"), ccb); 711*2d1d418eSSumit Saxena 712*2d1d418eSSumit Saxena return retval; 713*2d1d418eSSumit Saxena } 714*2d1d418eSSumit Saxena 715*2d1d418eSSumit Saxena /** 716*2d1d418eSSumit Saxena * mpi3mr_target_reset - Target reset error handling callback 717*2d1d418eSSumit Saxena * @cmd: Timed out command reference 718*2d1d418eSSumit Saxena * 719*2d1d418eSSumit Saxena * Issue Target reset Task Management and verify the SCSI commands are 720*2d1d418eSSumit Saxena * terminated successfully and return status accordingly. 721*2d1d418eSSumit Saxena * 722*2d1d418eSSumit Saxena * Return: SUCCESS of successful termination of the SCSI commands else 723*2d1d418eSSumit Saxena * FAILED 724*2d1d418eSSumit Saxena */ 725*2d1d418eSSumit Saxena static int mpi3mr_target_reset(struct mpi3mr_cmd *cmd) 726*2d1d418eSSumit Saxena { 727*2d1d418eSSumit Saxena int retval = 0; 728*2d1d418eSSumit Saxena struct mpi3mr_softc *sc; 729*2d1d418eSSumit Saxena struct mpi3mr_target *target; 730*2d1d418eSSumit Saxena 731*2d1d418eSSumit Saxena sc = cmd->sc; 732*2d1d418eSSumit Saxena 733*2d1d418eSSumit Saxena target = cmd->targ; 734*2d1d418eSSumit Saxena if (target == NULL) { 735*2d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_XINFO, "Device does not exist for target:0x%p," 736*2d1d418eSSumit Saxena "target reset is not required\n", target); 737*2d1d418eSSumit Saxena return retval; 738*2d1d418eSSumit Saxena } 739*2d1d418eSSumit Saxena 740*2d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_INFO, 741*2d1d418eSSumit Saxena "attempting target reset on target(%d)\n", target->per_id); 742*2d1d418eSSumit Saxena 743*2d1d418eSSumit Saxena 744*2d1d418eSSumit Saxena if (mpi3mr_atomic_read(&target->outstanding)) { 745*2d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_INFO, 746*2d1d418eSSumit Saxena "no outstanding IOs on the target(%d)," 747*2d1d418eSSumit Saxena " target reset not required.\n", target->per_id); 748*2d1d418eSSumit Saxena return retval; 749*2d1d418eSSumit Saxena } 750*2d1d418eSSumit Saxena 751*2d1d418eSSumit Saxena retval = mpi3mr_issue_tm(sc, cmd, MPI3_SCSITASKMGMT_TASKTYPE_TARGET_RESET, MPI3MR_RESETTM_TIMEOUT); 752*2d1d418eSSumit Saxena 753*2d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_INFO, 754*2d1d418eSSumit Saxena "target reset is %s for target(%d)\n", ((retval == 0) ? "SUCCESS" : "FAILED"), 755*2d1d418eSSumit Saxena target->per_id); 756*2d1d418eSSumit Saxena 757*2d1d418eSSumit Saxena return retval; 758*2d1d418eSSumit Saxena } 759*2d1d418eSSumit Saxena 760*2d1d418eSSumit Saxena /** 761*2d1d418eSSumit Saxena * mpi3mr_get_fw_pending_ios - Calculate pending I/O count 762*2d1d418eSSumit Saxena * @sc: Adapter instance reference 763*2d1d418eSSumit Saxena * 764*2d1d418eSSumit Saxena * Calculate the pending I/Os for the controller and return. 765*2d1d418eSSumit Saxena * 766*2d1d418eSSumit Saxena * Return: Number of pending I/Os 767*2d1d418eSSumit Saxena */ 768*2d1d418eSSumit Saxena static inline int mpi3mr_get_fw_pending_ios(struct mpi3mr_softc *sc) 769*2d1d418eSSumit Saxena { 770*2d1d418eSSumit Saxena U16 i, pend_ios = 0; 771*2d1d418eSSumit Saxena 772*2d1d418eSSumit Saxena for (i = 0; i < sc->num_queues; i++) 773*2d1d418eSSumit Saxena pend_ios += mpi3mr_atomic_read(&sc->op_reply_q[i].pend_ios); 774*2d1d418eSSumit Saxena return pend_ios; 775*2d1d418eSSumit Saxena } 776*2d1d418eSSumit Saxena 777*2d1d418eSSumit Saxena /** 778*2d1d418eSSumit Saxena * mpi3mr_wait_for_host_io - block for I/Os to complete 779*2d1d418eSSumit Saxena * @sc: Adapter instance reference 780*2d1d418eSSumit Saxena * @timeout: time out in seconds 781*2d1d418eSSumit Saxena * 782*2d1d418eSSumit Saxena * Waits for pending I/Os for the given adapter to complete or 783*2d1d418eSSumit Saxena * to hit the timeout. 784*2d1d418eSSumit Saxena * 785*2d1d418eSSumit Saxena * Return: Nothing 786*2d1d418eSSumit Saxena */ 787*2d1d418eSSumit Saxena static int mpi3mr_wait_for_host_io(struct mpi3mr_softc *sc, U32 timeout) 788*2d1d418eSSumit Saxena { 789*2d1d418eSSumit Saxena enum mpi3mr_iocstate iocstate; 790*2d1d418eSSumit Saxena 791*2d1d418eSSumit Saxena iocstate = mpi3mr_get_iocstate(sc); 792*2d1d418eSSumit Saxena if (iocstate != MRIOC_STATE_READY) { 793*2d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_XINFO, "%s :Controller is in NON-READY state! Proceed with Reset\n", __func__); 794*2d1d418eSSumit Saxena return -1; 795*2d1d418eSSumit Saxena } 796*2d1d418eSSumit Saxena 797*2d1d418eSSumit Saxena if (!mpi3mr_get_fw_pending_ios(sc)) 798*2d1d418eSSumit Saxena return 0; 799*2d1d418eSSumit Saxena 800*2d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_INFO, 801*2d1d418eSSumit Saxena "%s :Waiting for %d seconds prior to reset for %d pending I/Os to complete\n", 802*2d1d418eSSumit Saxena __func__, timeout, mpi3mr_get_fw_pending_ios(sc)); 803*2d1d418eSSumit Saxena 804*2d1d418eSSumit Saxena int i; 805*2d1d418eSSumit Saxena for (i = 0; i < timeout; i++) { 806*2d1d418eSSumit Saxena if (!mpi3mr_get_fw_pending_ios(sc)) { 807*2d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_INFO, "%s :All pending I/Os got completed while waiting! Reset not required\n", __func__); 808*2d1d418eSSumit Saxena return 0; 809*2d1d418eSSumit Saxena 810*2d1d418eSSumit Saxena } 811*2d1d418eSSumit Saxena iocstate = mpi3mr_get_iocstate(sc); 812*2d1d418eSSumit Saxena if (iocstate != MRIOC_STATE_READY) { 813*2d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_XINFO, "%s :Controller state becomes NON-READY while waiting! dont wait further" 814*2d1d418eSSumit Saxena "Proceed with Reset\n", __func__); 815*2d1d418eSSumit Saxena return -1; 816*2d1d418eSSumit Saxena } 817*2d1d418eSSumit Saxena DELAY(1000 * 1000); 818*2d1d418eSSumit Saxena } 819*2d1d418eSSumit Saxena 820*2d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_INFO, "%s :Pending I/Os after wait exaust is %d! Proceed with Reset\n", __func__, 821*2d1d418eSSumit Saxena mpi3mr_get_fw_pending_ios(sc)); 822*2d1d418eSSumit Saxena 823*2d1d418eSSumit Saxena return -1; 824*2d1d418eSSumit Saxena } 825*2d1d418eSSumit Saxena 826*2d1d418eSSumit Saxena static void 827*2d1d418eSSumit Saxena mpi3mr_scsiio_timeout(void *data) 828*2d1d418eSSumit Saxena { 829*2d1d418eSSumit Saxena int retval = 0; 830*2d1d418eSSumit Saxena struct mpi3mr_softc *sc; 831*2d1d418eSSumit Saxena struct mpi3mr_cmd *cmd; 832*2d1d418eSSumit Saxena struct mpi3mr_target *targ_dev = NULL; 833*2d1d418eSSumit Saxena 834*2d1d418eSSumit Saxena if (!data) 835*2d1d418eSSumit Saxena return; 836*2d1d418eSSumit Saxena 837*2d1d418eSSumit Saxena cmd = (struct mpi3mr_cmd *)data; 838*2d1d418eSSumit Saxena sc = cmd->sc; 839*2d1d418eSSumit Saxena 840*2d1d418eSSumit Saxena if (cmd->ccb == NULL) { 841*2d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_ERROR, "SCSIIO command timed-out with NULL ccb\n"); 842*2d1d418eSSumit Saxena return; 843*2d1d418eSSumit Saxena } 844*2d1d418eSSumit Saxena 845*2d1d418eSSumit Saxena /* 846*2d1d418eSSumit Saxena * TMs are not supported for IO timeouts on VD/LD, so directly issue controller reset 847*2d1d418eSSumit Saxena * with max timeout for outstanding IOs to complete is 180sec. 848*2d1d418eSSumit Saxena */ 849*2d1d418eSSumit Saxena targ_dev = cmd->targ; 850*2d1d418eSSumit Saxena if (targ_dev && (targ_dev->dev_type == MPI3_DEVICE_DEVFORM_VD)) { 851*2d1d418eSSumit Saxena if (mpi3mr_wait_for_host_io(sc, MPI3MR_RAID_ERRREC_RESET_TIMEOUT)) 852*2d1d418eSSumit Saxena trigger_reset_from_watchdog(sc, MPI3MR_TRIGGER_SOFT_RESET, MPI3MR_RESET_FROM_SCSIIO_TIMEOUT); 853*2d1d418eSSumit Saxena return; 854*2d1d418eSSumit Saxena } 855*2d1d418eSSumit Saxena 856*2d1d418eSSumit Saxena /* Issue task abort to recover the timed out IO */ 857*2d1d418eSSumit Saxena retval = mpi3mr_task_abort(cmd); 858*2d1d418eSSumit Saxena if (!retval || (retval == ETIMEDOUT)) 859*2d1d418eSSumit Saxena return; 860*2d1d418eSSumit Saxena 861*2d1d418eSSumit Saxena /* 862*2d1d418eSSumit Saxena * task abort has failed to recover the timed out IO, 863*2d1d418eSSumit Saxena * try with the target reset 864*2d1d418eSSumit Saxena */ 865*2d1d418eSSumit Saxena retval = mpi3mr_target_reset(cmd); 866*2d1d418eSSumit Saxena if (!retval || (retval == ETIMEDOUT)) 867*2d1d418eSSumit Saxena return; 868*2d1d418eSSumit Saxena 869*2d1d418eSSumit Saxena /* 870*2d1d418eSSumit Saxena * task abort and target reset has failed. So issue Controller reset(soft reset) 871*2d1d418eSSumit Saxena * through OCR thread context 872*2d1d418eSSumit Saxena */ 873*2d1d418eSSumit Saxena trigger_reset_from_watchdog(sc, MPI3MR_TRIGGER_SOFT_RESET, MPI3MR_RESET_FROM_SCSIIO_TIMEOUT); 874*2d1d418eSSumit Saxena 875*2d1d418eSSumit Saxena return; 876*2d1d418eSSumit Saxena } 877*2d1d418eSSumit Saxena 878*2d1d418eSSumit Saxena void int_to_lun(unsigned int lun, U8 *req_lun) 879*2d1d418eSSumit Saxena { 880*2d1d418eSSumit Saxena int i; 881*2d1d418eSSumit Saxena 882*2d1d418eSSumit Saxena memset(req_lun, 0, sizeof(*req_lun)); 883*2d1d418eSSumit Saxena 884*2d1d418eSSumit Saxena for (i = 0; i < sizeof(lun); i += 2) { 885*2d1d418eSSumit Saxena req_lun[i] = (lun >> 8) & 0xFF; 886*2d1d418eSSumit Saxena req_lun[i+1] = lun & 0xFF; 887*2d1d418eSSumit Saxena lun = lun >> 16; 888*2d1d418eSSumit Saxena } 889*2d1d418eSSumit Saxena 890*2d1d418eSSumit Saxena } 891*2d1d418eSSumit Saxena 892*2d1d418eSSumit Saxena static U16 get_req_queue_index(struct mpi3mr_softc *sc) 893*2d1d418eSSumit Saxena { 894*2d1d418eSSumit Saxena U16 i = 0, reply_q_index = 0, reply_q_pend_ios = 0; 895*2d1d418eSSumit Saxena 896*2d1d418eSSumit Saxena reply_q_pend_ios = mpi3mr_atomic_read(&sc->op_reply_q[0].pend_ios); 897*2d1d418eSSumit Saxena for (i = 0; i < sc->num_queues; i++) { 898*2d1d418eSSumit Saxena if (reply_q_pend_ios > mpi3mr_atomic_read(&sc->op_reply_q[i].pend_ios)) { 899*2d1d418eSSumit Saxena reply_q_pend_ios = mpi3mr_atomic_read(&sc->op_reply_q[i].pend_ios); 900*2d1d418eSSumit Saxena reply_q_index = i; 901*2d1d418eSSumit Saxena } 902*2d1d418eSSumit Saxena } 903*2d1d418eSSumit Saxena 904*2d1d418eSSumit Saxena return reply_q_index; 905*2d1d418eSSumit Saxena } 906*2d1d418eSSumit Saxena 907*2d1d418eSSumit Saxena static void 908*2d1d418eSSumit Saxena mpi3mr_action_scsiio(struct mpi3mr_cam_softc *cam_sc, union ccb *ccb) 909*2d1d418eSSumit Saxena { 910*2d1d418eSSumit Saxena Mpi3SCSIIORequest_t *req = NULL; 911*2d1d418eSSumit Saxena struct ccb_scsiio *csio; 912*2d1d418eSSumit Saxena struct mpi3mr_softc *sc; 913*2d1d418eSSumit Saxena struct mpi3mr_target *targ; 914*2d1d418eSSumit Saxena struct mpi3mr_cmd *cm; 915*2d1d418eSSumit Saxena uint8_t scsi_opcode, queue_idx; 916*2d1d418eSSumit Saxena uint32_t mpi_control; 917*2d1d418eSSumit Saxena struct mpi3mr_op_req_queue *opreqq = NULL; 918*2d1d418eSSumit Saxena U32 data_len_blks = 0; 919*2d1d418eSSumit Saxena U32 tracked_io_sz = 0; 920*2d1d418eSSumit Saxena U32 ioc_pend_data_len = 0, tg_pend_data_len = 0; 921*2d1d418eSSumit Saxena struct mpi3mr_throttle_group_info *tg = NULL; 922*2d1d418eSSumit Saxena static int ratelimit; 923*2d1d418eSSumit Saxena 924*2d1d418eSSumit Saxena sc = cam_sc->sc; 925*2d1d418eSSumit Saxena mtx_assert(&sc->mpi3mr_mtx, MA_OWNED); 926*2d1d418eSSumit Saxena 927*2d1d418eSSumit Saxena if (sc->unrecoverable) { 928*2d1d418eSSumit Saxena mpi3mr_set_ccbstatus(ccb, CAM_DEV_NOT_THERE); 929*2d1d418eSSumit Saxena xpt_done(ccb); 930*2d1d418eSSumit Saxena return; 931*2d1d418eSSumit Saxena } 932*2d1d418eSSumit Saxena 933*2d1d418eSSumit Saxena csio = &ccb->csio; 934*2d1d418eSSumit Saxena KASSERT(csio->ccb_h.target_id < cam_sc->maxtargets, 935*2d1d418eSSumit Saxena ("Target %d out of bounds in XPT_SCSI_IO\n", 936*2d1d418eSSumit Saxena csio->ccb_h.target_id)); 937*2d1d418eSSumit Saxena 938*2d1d418eSSumit Saxena scsi_opcode = scsiio_cdb_ptr(csio)[0]; 939*2d1d418eSSumit Saxena 940*2d1d418eSSumit Saxena if ((sc->mpi3mr_flags & MPI3MR_FLAGS_SHUTDOWN) && 941*2d1d418eSSumit Saxena !((scsi_opcode == SYNCHRONIZE_CACHE) || 942*2d1d418eSSumit Saxena (scsi_opcode == START_STOP_UNIT))) { 943*2d1d418eSSumit Saxena mpi3mr_set_ccbstatus(ccb, CAM_REQ_CMP); 944*2d1d418eSSumit Saxena xpt_done(ccb); 945*2d1d418eSSumit Saxena return; 946*2d1d418eSSumit Saxena } 947*2d1d418eSSumit Saxena 948*2d1d418eSSumit Saxena targ = mpi3mr_find_target_by_per_id(cam_sc, csio->ccb_h.target_id); 949*2d1d418eSSumit Saxena if (targ == NULL) { 950*2d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_XINFO, "Device with target ID: 0x%x does not exist\n", 951*2d1d418eSSumit Saxena csio->ccb_h.target_id); 952*2d1d418eSSumit Saxena mpi3mr_set_ccbstatus(ccb, CAM_DEV_NOT_THERE); 953*2d1d418eSSumit Saxena xpt_done(ccb); 954*2d1d418eSSumit Saxena return; 955*2d1d418eSSumit Saxena } 956*2d1d418eSSumit Saxena 957*2d1d418eSSumit Saxena if (targ && targ->is_hidden) { 958*2d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_XINFO, "Device with target ID: 0x%x is hidden\n", 959*2d1d418eSSumit Saxena csio->ccb_h.target_id); 960*2d1d418eSSumit Saxena mpi3mr_set_ccbstatus(ccb, CAM_DEV_NOT_THERE); 961*2d1d418eSSumit Saxena xpt_done(ccb); 962*2d1d418eSSumit Saxena return; 963*2d1d418eSSumit Saxena } 964*2d1d418eSSumit Saxena 965*2d1d418eSSumit Saxena if (targ->dev_removed == 1) { 966*2d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_XINFO, "Device with target ID: 0x%x is removed\n", csio->ccb_h.target_id); 967*2d1d418eSSumit Saxena mpi3mr_set_ccbstatus(ccb, CAM_DEV_NOT_THERE); 968*2d1d418eSSumit Saxena xpt_done(ccb); 969*2d1d418eSSumit Saxena return; 970*2d1d418eSSumit Saxena } 971*2d1d418eSSumit Saxena 972*2d1d418eSSumit Saxena if (targ->dev_handle == 0x0) { 973*2d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_ERROR, "%s NULL handle for target 0x%x\n", 974*2d1d418eSSumit Saxena __func__, csio->ccb_h.target_id); 975*2d1d418eSSumit Saxena mpi3mr_set_ccbstatus(ccb, CAM_DEV_NOT_THERE); 976*2d1d418eSSumit Saxena xpt_done(ccb); 977*2d1d418eSSumit Saxena return; 978*2d1d418eSSumit Saxena } 979*2d1d418eSSumit Saxena 980*2d1d418eSSumit Saxena if (mpi3mr_atomic_read(&targ->block_io) || 981*2d1d418eSSumit Saxena (sc->reset_in_progress == 1) || (sc->prepare_for_reset == 1)) { 982*2d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_TRACE, "%s target is busy target_id: 0x%x\n", 983*2d1d418eSSumit Saxena __func__, csio->ccb_h.target_id); 984*2d1d418eSSumit Saxena mpi3mr_set_ccbstatus(ccb, CAM_REQUEUE_REQ); 985*2d1d418eSSumit Saxena xpt_done(ccb); 986*2d1d418eSSumit Saxena return; 987*2d1d418eSSumit Saxena } 988*2d1d418eSSumit Saxena 989*2d1d418eSSumit Saxena /* 990*2d1d418eSSumit Saxena * Sometimes, it is possible to get a command that is not "In 991*2d1d418eSSumit Saxena * Progress" and was actually aborted by the upper layer. Check for 992*2d1d418eSSumit Saxena * this here and complete the command without error. 993*2d1d418eSSumit Saxena */ 994*2d1d418eSSumit Saxena if (mpi3mr_get_ccbstatus(ccb) != CAM_REQ_INPROG) { 995*2d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_TRACE, "%s Command is not in progress for " 996*2d1d418eSSumit Saxena "target %u\n", __func__, csio->ccb_h.target_id); 997*2d1d418eSSumit Saxena xpt_done(ccb); 998*2d1d418eSSumit Saxena return; 999*2d1d418eSSumit Saxena } 1000*2d1d418eSSumit Saxena /* 1001*2d1d418eSSumit Saxena * If devinfo is 0 this will be a volume. In that case don't tell CAM 1002*2d1d418eSSumit Saxena * that the volume has timed out. We want volumes to be enumerated 1003*2d1d418eSSumit Saxena * until they are deleted/removed, not just failed. 1004*2d1d418eSSumit Saxena */ 1005*2d1d418eSSumit Saxena if (targ->flags & MPI3MRSAS_TARGET_INREMOVAL) { 1006*2d1d418eSSumit Saxena if (targ->devinfo == 0) 1007*2d1d418eSSumit Saxena mpi3mr_set_ccbstatus(ccb, CAM_REQ_CMP); 1008*2d1d418eSSumit Saxena else 1009*2d1d418eSSumit Saxena mpi3mr_set_ccbstatus(ccb, CAM_SEL_TIMEOUT); 1010*2d1d418eSSumit Saxena xpt_done(ccb); 1011*2d1d418eSSumit Saxena return; 1012*2d1d418eSSumit Saxena } 1013*2d1d418eSSumit Saxena 1014*2d1d418eSSumit Saxena if ((scsi_opcode == UNMAP) && 1015*2d1d418eSSumit Saxena (pci_get_device(sc->mpi3mr_dev) == MPI3_MFGPAGE_DEVID_SAS4116) && 1016*2d1d418eSSumit Saxena (targ->dev_type == MPI3_DEVICE_DEVFORM_PCIE) && 1017*2d1d418eSSumit Saxena (mpi3mr_allow_unmap_to_fw(sc, ccb) == false)) 1018*2d1d418eSSumit Saxena return; 1019*2d1d418eSSumit Saxena 1020*2d1d418eSSumit Saxena cm = mpi3mr_get_command(sc); 1021*2d1d418eSSumit Saxena if (cm == NULL || (sc->mpi3mr_flags & MPI3MR_FLAGS_DIAGRESET)) { 1022*2d1d418eSSumit Saxena if (cm != NULL) { 1023*2d1d418eSSumit Saxena mpi3mr_release_command(cm); 1024*2d1d418eSSumit Saxena } 1025*2d1d418eSSumit Saxena if ((cam_sc->flags & MPI3MRSAS_QUEUE_FROZEN) == 0) { 1026*2d1d418eSSumit Saxena xpt_freeze_simq(cam_sc->sim, 1); 1027*2d1d418eSSumit Saxena cam_sc->flags |= MPI3MRSAS_QUEUE_FROZEN; 1028*2d1d418eSSumit Saxena } 1029*2d1d418eSSumit Saxena ccb->ccb_h.status &= ~CAM_SIM_QUEUED; 1030*2d1d418eSSumit Saxena ccb->ccb_h.status |= CAM_REQUEUE_REQ; 1031*2d1d418eSSumit Saxena xpt_done(ccb); 1032*2d1d418eSSumit Saxena return; 1033*2d1d418eSSumit Saxena } 1034*2d1d418eSSumit Saxena 1035*2d1d418eSSumit Saxena switch (csio->ccb_h.flags & CAM_DIR_MASK) { 1036*2d1d418eSSumit Saxena case CAM_DIR_IN: 1037*2d1d418eSSumit Saxena mpi_control = MPI3_SCSIIO_FLAGS_DATADIRECTION_READ; 1038*2d1d418eSSumit Saxena cm->data_dir = MPI3MR_READ; 1039*2d1d418eSSumit Saxena break; 1040*2d1d418eSSumit Saxena case CAM_DIR_OUT: 1041*2d1d418eSSumit Saxena mpi_control = MPI3_SCSIIO_FLAGS_DATADIRECTION_WRITE; 1042*2d1d418eSSumit Saxena cm->data_dir = MPI3MR_WRITE; 1043*2d1d418eSSumit Saxena break; 1044*2d1d418eSSumit Saxena case CAM_DIR_NONE: 1045*2d1d418eSSumit Saxena default: 1046*2d1d418eSSumit Saxena mpi_control = MPI3_SCSIIO_FLAGS_DATADIRECTION_NO_DATA_TRANSFER; 1047*2d1d418eSSumit Saxena break; 1048*2d1d418eSSumit Saxena } 1049*2d1d418eSSumit Saxena 1050*2d1d418eSSumit Saxena if (csio->cdb_len > 16) 1051*2d1d418eSSumit Saxena mpi_control |= MPI3_SCSIIO_FLAGS_CDB_GREATER_THAN_16; 1052*2d1d418eSSumit Saxena 1053*2d1d418eSSumit Saxena req = (Mpi3SCSIIORequest_t *)&cm->io_request; 1054*2d1d418eSSumit Saxena bzero(req, sizeof(*req)); 1055*2d1d418eSSumit Saxena req->Function = MPI3_FUNCTION_SCSI_IO; 1056*2d1d418eSSumit Saxena req->HostTag = cm->hosttag; 1057*2d1d418eSSumit Saxena req->DataLength = htole32(csio->dxfer_len); 1058*2d1d418eSSumit Saxena req->DevHandle = htole16(targ->dev_handle); 1059*2d1d418eSSumit Saxena 1060*2d1d418eSSumit Saxena /* 1061*2d1d418eSSumit Saxena * It looks like the hardware doesn't require an explicit tag 1062*2d1d418eSSumit Saxena * number for each transaction. SAM Task Management not supported 1063*2d1d418eSSumit Saxena * at the moment. 1064*2d1d418eSSumit Saxena */ 1065*2d1d418eSSumit Saxena switch (csio->tag_action) { 1066*2d1d418eSSumit Saxena case MSG_HEAD_OF_Q_TAG: 1067*2d1d418eSSumit Saxena mpi_control |= MPI3_SCSIIO_FLAGS_TASKATTRIBUTE_HEADOFQ; 1068*2d1d418eSSumit Saxena break; 1069*2d1d418eSSumit Saxena case MSG_ORDERED_Q_TAG: 1070*2d1d418eSSumit Saxena mpi_control |= MPI3_SCSIIO_FLAGS_TASKATTRIBUTE_ORDEREDQ; 1071*2d1d418eSSumit Saxena break; 1072*2d1d418eSSumit Saxena case MSG_ACA_TASK: 1073*2d1d418eSSumit Saxena mpi_control |= MPI3_SCSIIO_FLAGS_TASKATTRIBUTE_ACAQ; 1074*2d1d418eSSumit Saxena break; 1075*2d1d418eSSumit Saxena case CAM_TAG_ACTION_NONE: 1076*2d1d418eSSumit Saxena case MSG_SIMPLE_Q_TAG: 1077*2d1d418eSSumit Saxena default: 1078*2d1d418eSSumit Saxena mpi_control |= MPI3_SCSIIO_FLAGS_TASKATTRIBUTE_SIMPLEQ; 1079*2d1d418eSSumit Saxena break; 1080*2d1d418eSSumit Saxena } 1081*2d1d418eSSumit Saxena 1082*2d1d418eSSumit Saxena req->Flags = htole32(mpi_control); 1083*2d1d418eSSumit Saxena 1084*2d1d418eSSumit Saxena if (csio->ccb_h.flags & CAM_CDB_POINTER) 1085*2d1d418eSSumit Saxena bcopy(csio->cdb_io.cdb_ptr, &req->CDB.CDB32[0], csio->cdb_len); 1086*2d1d418eSSumit Saxena else { 1087*2d1d418eSSumit Saxena KASSERT(csio->cdb_len <= IOCDBLEN, 1088*2d1d418eSSumit Saxena ("cdb_len %d is greater than IOCDBLEN but CAM_CDB_POINTER " 1089*2d1d418eSSumit Saxena "is not set", csio->cdb_len)); 1090*2d1d418eSSumit Saxena bcopy(csio->cdb_io.cdb_bytes, &req->CDB.CDB32[0],csio->cdb_len); 1091*2d1d418eSSumit Saxena } 1092*2d1d418eSSumit Saxena 1093*2d1d418eSSumit Saxena cm->length = csio->dxfer_len; 1094*2d1d418eSSumit Saxena cm->targ = targ; 1095*2d1d418eSSumit Saxena int_to_lun(csio->ccb_h.target_lun, req->LUN); 1096*2d1d418eSSumit Saxena cm->ccb = ccb; 1097*2d1d418eSSumit Saxena csio->ccb_h.qos.sim_data = sbinuptime(); 1098*2d1d418eSSumit Saxena queue_idx = get_req_queue_index(sc); 1099*2d1d418eSSumit Saxena cm->req_qidx = queue_idx; 1100*2d1d418eSSumit Saxena 1101*2d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_TRACE, "[QID:%d]: func: %s line:%d CDB: 0x%x targetid: %x SMID: 0x%x\n", 1102*2d1d418eSSumit Saxena (queue_idx + 1), __func__, __LINE__, scsi_opcode, csio->ccb_h.target_id, cm->hosttag); 1103*2d1d418eSSumit Saxena 1104*2d1d418eSSumit Saxena ccb->ccb_h.status |= CAM_SIM_QUEUED; 1105*2d1d418eSSumit Saxena 1106*2d1d418eSSumit Saxena switch ((ccb->ccb_h.flags & CAM_DATA_MASK)) { 1107*2d1d418eSSumit Saxena case CAM_DATA_PADDR: 1108*2d1d418eSSumit Saxena case CAM_DATA_SG_PADDR: 1109*2d1d418eSSumit Saxena device_printf(sc->mpi3mr_dev, "%s: physical addresses not supported\n", 1110*2d1d418eSSumit Saxena __func__); 1111*2d1d418eSSumit Saxena mpi3mr_release_command(cm); 1112*2d1d418eSSumit Saxena ccb->ccb_h.status = CAM_REQ_INVALID; 1113*2d1d418eSSumit Saxena ccb->ccb_h.status &= ~CAM_SIM_QUEUED; 1114*2d1d418eSSumit Saxena xpt_done(ccb); 1115*2d1d418eSSumit Saxena return; 1116*2d1d418eSSumit Saxena case CAM_DATA_SG: 1117*2d1d418eSSumit Saxena device_printf(sc->mpi3mr_dev, "%s: scatter gather is not supported\n", 1118*2d1d418eSSumit Saxena __func__); 1119*2d1d418eSSumit Saxena mpi3mr_release_command(cm); 1120*2d1d418eSSumit Saxena ccb->ccb_h.status = CAM_REQ_INVALID; 1121*2d1d418eSSumit Saxena xpt_done(ccb); 1122*2d1d418eSSumit Saxena return; 1123*2d1d418eSSumit Saxena case CAM_DATA_VADDR: 1124*2d1d418eSSumit Saxena case CAM_DATA_BIO: 1125*2d1d418eSSumit Saxena if (csio->dxfer_len > (MPI3MR_SG_DEPTH * MPI3MR_4K_PGSZ)) { 1126*2d1d418eSSumit Saxena mpi3mr_release_command(cm); 1127*2d1d418eSSumit Saxena ccb->ccb_h.status = CAM_REQ_TOO_BIG; 1128*2d1d418eSSumit Saxena xpt_done(ccb); 1129*2d1d418eSSumit Saxena return; 1130*2d1d418eSSumit Saxena } 1131*2d1d418eSSumit Saxena cm->length = csio->dxfer_len; 1132*2d1d418eSSumit Saxena if (cm->length) 1133*2d1d418eSSumit Saxena cm->data = csio->data_ptr; 1134*2d1d418eSSumit Saxena break; 1135*2d1d418eSSumit Saxena default: 1136*2d1d418eSSumit Saxena ccb->ccb_h.status = CAM_REQ_INVALID; 1137*2d1d418eSSumit Saxena xpt_done(ccb); 1138*2d1d418eSSumit Saxena return; 1139*2d1d418eSSumit Saxena } 1140*2d1d418eSSumit Saxena 1141*2d1d418eSSumit Saxena /* Prepare SGEs */ 1142*2d1d418eSSumit Saxena if (mpi3mr_map_request(sc, cm)) { 1143*2d1d418eSSumit Saxena mpi3mr_release_command(cm); 1144*2d1d418eSSumit Saxena xpt_done(ccb); 1145*2d1d418eSSumit Saxena printf("func: %s line: %d Build SGLs failed\n", __func__, __LINE__); 1146*2d1d418eSSumit Saxena return; 1147*2d1d418eSSumit Saxena } 1148*2d1d418eSSumit Saxena 1149*2d1d418eSSumit Saxena opreqq = &sc->op_req_q[queue_idx]; 1150*2d1d418eSSumit Saxena 1151*2d1d418eSSumit Saxena if (sc->iot_enable) { 1152*2d1d418eSSumit Saxena data_len_blks = csio->dxfer_len >> 9; 1153*2d1d418eSSumit Saxena 1154*2d1d418eSSumit Saxena if ((data_len_blks >= sc->io_throttle_data_length) && 1155*2d1d418eSSumit Saxena targ->io_throttle_enabled) { 1156*2d1d418eSSumit Saxena tracked_io_sz = data_len_blks; 1157*2d1d418eSSumit Saxena tg = targ->throttle_group; 1158*2d1d418eSSumit Saxena if (tg) { 1159*2d1d418eSSumit Saxena mpi3mr_atomic_add(&sc->pend_large_data_sz, data_len_blks); 1160*2d1d418eSSumit Saxena mpi3mr_atomic_add(&tg->pend_large_data_sz, data_len_blks); 1161*2d1d418eSSumit Saxena 1162*2d1d418eSSumit Saxena ioc_pend_data_len = mpi3mr_atomic_read(&sc->pend_large_data_sz); 1163*2d1d418eSSumit Saxena tg_pend_data_len = mpi3mr_atomic_read(&tg->pend_large_data_sz); 1164*2d1d418eSSumit Saxena 1165*2d1d418eSSumit Saxena if (ratelimit % 1000) { 1166*2d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_IOT, 1167*2d1d418eSSumit Saxena "large vd_io persist_id(%d), handle(0x%04x), data_len(%d)," 1168*2d1d418eSSumit Saxena "ioc_pending(%d), tg_pending(%d), ioc_high(%d), tg_high(%d)\n", 1169*2d1d418eSSumit Saxena targ->per_id, targ->dev_handle, 1170*2d1d418eSSumit Saxena data_len_blks, ioc_pend_data_len, 1171*2d1d418eSSumit Saxena tg_pend_data_len, sc->io_throttle_high, 1172*2d1d418eSSumit Saxena tg->high); 1173*2d1d418eSSumit Saxena ratelimit++; 1174*2d1d418eSSumit Saxena } 1175*2d1d418eSSumit Saxena 1176*2d1d418eSSumit Saxena if (!tg->io_divert && ((ioc_pend_data_len >= 1177*2d1d418eSSumit Saxena sc->io_throttle_high) || 1178*2d1d418eSSumit Saxena (tg_pend_data_len >= tg->high))) { 1179*2d1d418eSSumit Saxena tg->io_divert = 1; 1180*2d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_IOT, 1181*2d1d418eSSumit Saxena "VD: Setting divert flag for tg_id(%d), persist_id(%d)\n", 1182*2d1d418eSSumit Saxena tg->id, targ->per_id); 1183*2d1d418eSSumit Saxena if (sc->mpi3mr_debug | MPI3MR_IOT) 1184*2d1d418eSSumit Saxena mpi3mr_print_cdb(ccb); 1185*2d1d418eSSumit Saxena mpi3mr_set_io_divert_for_all_vd_in_tg(sc, 1186*2d1d418eSSumit Saxena tg, 1); 1187*2d1d418eSSumit Saxena } 1188*2d1d418eSSumit Saxena } else { 1189*2d1d418eSSumit Saxena mpi3mr_atomic_add(&sc->pend_large_data_sz, data_len_blks); 1190*2d1d418eSSumit Saxena ioc_pend_data_len = mpi3mr_atomic_read(&sc->pend_large_data_sz); 1191*2d1d418eSSumit Saxena if (ratelimit % 1000) { 1192*2d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_IOT, 1193*2d1d418eSSumit Saxena "large pd_io persist_id(%d), handle(0x%04x), data_len(%d), ioc_pending(%d), ioc_high(%d)\n", 1194*2d1d418eSSumit Saxena targ->per_id, targ->dev_handle, 1195*2d1d418eSSumit Saxena data_len_blks, ioc_pend_data_len, 1196*2d1d418eSSumit Saxena sc->io_throttle_high); 1197*2d1d418eSSumit Saxena ratelimit++; 1198*2d1d418eSSumit Saxena } 1199*2d1d418eSSumit Saxena 1200*2d1d418eSSumit Saxena if (ioc_pend_data_len >= sc->io_throttle_high) { 1201*2d1d418eSSumit Saxena targ->io_divert = 1; 1202*2d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_IOT, 1203*2d1d418eSSumit Saxena "PD: Setting divert flag for persist_id(%d)\n", 1204*2d1d418eSSumit Saxena targ->per_id); 1205*2d1d418eSSumit Saxena if (sc->mpi3mr_debug | MPI3MR_IOT) 1206*2d1d418eSSumit Saxena mpi3mr_print_cdb(ccb); 1207*2d1d418eSSumit Saxena } 1208*2d1d418eSSumit Saxena } 1209*2d1d418eSSumit Saxena } 1210*2d1d418eSSumit Saxena 1211*2d1d418eSSumit Saxena if (targ->io_divert) { 1212*2d1d418eSSumit Saxena req->MsgFlags |= MPI3_SCSIIO_MSGFLAGS_DIVERT_TO_FIRMWARE; 1213*2d1d418eSSumit Saxena mpi_control |= MPI3_SCSIIO_FLAGS_DIVERT_REASON_IO_THROTTLING; 1214*2d1d418eSSumit Saxena } 1215*2d1d418eSSumit Saxena } 1216*2d1d418eSSumit Saxena req->Flags = htole32(mpi_control); 1217*2d1d418eSSumit Saxena 1218*2d1d418eSSumit Saxena if (mpi3mr_submit_io(sc, opreqq, 1219*2d1d418eSSumit Saxena (U8 *)&cm->io_request)) { 1220*2d1d418eSSumit Saxena mpi3mr_release_command(cm); 1221*2d1d418eSSumit Saxena if (tracked_io_sz) { 1222*2d1d418eSSumit Saxena mpi3mr_atomic_sub(&sc->pend_large_data_sz, tracked_io_sz); 1223*2d1d418eSSumit Saxena if (tg) 1224*2d1d418eSSumit Saxena mpi3mr_atomic_sub(&tg->pend_large_data_sz, tracked_io_sz); 1225*2d1d418eSSumit Saxena } 1226*2d1d418eSSumit Saxena mpi3mr_set_ccbstatus(ccb, CAM_RESRC_UNAVAIL); 1227*2d1d418eSSumit Saxena xpt_done(ccb); 1228*2d1d418eSSumit Saxena } else { 1229*2d1d418eSSumit Saxena callout_reset_sbt(&cm->callout, SBT_1S * 90 , 0, 1230*2d1d418eSSumit Saxena mpi3mr_scsiio_timeout, cm, 0); 1231*2d1d418eSSumit Saxena mpi3mr_atomic_inc(&sc->fw_outstanding); 1232*2d1d418eSSumit Saxena mpi3mr_atomic_inc(&targ->outstanding); 1233*2d1d418eSSumit Saxena if (mpi3mr_atomic_read(&sc->fw_outstanding) > sc->io_cmds_highwater) 1234*2d1d418eSSumit Saxena sc->io_cmds_highwater++; 1235*2d1d418eSSumit Saxena } 1236*2d1d418eSSumit Saxena 1237*2d1d418eSSumit Saxena cm->callout_owner = true; 1238*2d1d418eSSumit Saxena return; 1239*2d1d418eSSumit Saxena } 1240*2d1d418eSSumit Saxena 1241*2d1d418eSSumit Saxena static void 1242*2d1d418eSSumit Saxena mpi3mr_cam_poll(struct cam_sim *sim) 1243*2d1d418eSSumit Saxena { 1244*2d1d418eSSumit Saxena struct mpi3mr_cam_softc *cam_sc; 1245*2d1d418eSSumit Saxena struct mpi3mr_irq_context *irq_ctx; 1246*2d1d418eSSumit Saxena struct mpi3mr_softc *sc; 1247*2d1d418eSSumit Saxena int i; 1248*2d1d418eSSumit Saxena 1249*2d1d418eSSumit Saxena cam_sc = cam_sim_softc(sim); 1250*2d1d418eSSumit Saxena sc = cam_sc->sc; 1251*2d1d418eSSumit Saxena 1252*2d1d418eSSumit Saxena mpi3mr_dprint(cam_sc->sc, MPI3MR_TRACE, "func: %s line: %d is called\n", 1253*2d1d418eSSumit Saxena __func__, __LINE__); 1254*2d1d418eSSumit Saxena 1255*2d1d418eSSumit Saxena for (i = 0; i < sc->num_queues; i++) { 1256*2d1d418eSSumit Saxena irq_ctx = sc->irq_ctx + i; 1257*2d1d418eSSumit Saxena if (irq_ctx->op_reply_q->qid) { 1258*2d1d418eSSumit Saxena mpi3mr_complete_io_cmd(sc, irq_ctx); 1259*2d1d418eSSumit Saxena } 1260*2d1d418eSSumit Saxena } 1261*2d1d418eSSumit Saxena } 1262*2d1d418eSSumit Saxena 1263*2d1d418eSSumit Saxena static void 1264*2d1d418eSSumit Saxena mpi3mr_cam_action(struct cam_sim *sim, union ccb *ccb) 1265*2d1d418eSSumit Saxena { 1266*2d1d418eSSumit Saxena struct mpi3mr_cam_softc *cam_sc; 1267*2d1d418eSSumit Saxena struct mpi3mr_target *targ; 1268*2d1d418eSSumit Saxena 1269*2d1d418eSSumit Saxena cam_sc = cam_sim_softc(sim); 1270*2d1d418eSSumit Saxena 1271*2d1d418eSSumit Saxena mpi3mr_dprint(cam_sc->sc, MPI3MR_TRACE, "ccb func_code 0x%x target id: 0x%x\n", 1272*2d1d418eSSumit Saxena ccb->ccb_h.func_code, ccb->ccb_h.target_id); 1273*2d1d418eSSumit Saxena 1274*2d1d418eSSumit Saxena mtx_assert(&cam_sc->sc->mpi3mr_mtx, MA_OWNED); 1275*2d1d418eSSumit Saxena 1276*2d1d418eSSumit Saxena switch (ccb->ccb_h.func_code) { 1277*2d1d418eSSumit Saxena case XPT_PATH_INQ: 1278*2d1d418eSSumit Saxena { 1279*2d1d418eSSumit Saxena struct ccb_pathinq *cpi = &ccb->cpi; 1280*2d1d418eSSumit Saxena 1281*2d1d418eSSumit Saxena cpi->version_num = 1; 1282*2d1d418eSSumit Saxena cpi->hba_inquiry = PI_SDTR_ABLE|PI_TAG_ABLE|PI_WIDE_16; 1283*2d1d418eSSumit Saxena cpi->target_sprt = 0; 1284*2d1d418eSSumit Saxena cpi->hba_misc = PIM_NOBUSRESET | PIM_UNMAPPED | PIM_NOSCAN; 1285*2d1d418eSSumit Saxena cpi->hba_eng_cnt = 0; 1286*2d1d418eSSumit Saxena cpi->max_target = cam_sc->maxtargets - 1; 1287*2d1d418eSSumit Saxena cpi->max_lun = 0; 1288*2d1d418eSSumit Saxena 1289*2d1d418eSSumit Saxena /* 1290*2d1d418eSSumit Saxena * initiator_id is set here to an ID outside the set of valid 1291*2d1d418eSSumit Saxena * target IDs (including volumes). 1292*2d1d418eSSumit Saxena */ 1293*2d1d418eSSumit Saxena cpi->initiator_id = cam_sc->maxtargets; 1294*2d1d418eSSumit Saxena strlcpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN); 1295*2d1d418eSSumit Saxena strlcpy(cpi->hba_vid, "Broadcom", HBA_IDLEN); 1296*2d1d418eSSumit Saxena strlcpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN); 1297*2d1d418eSSumit Saxena cpi->unit_number = cam_sim_unit(sim); 1298*2d1d418eSSumit Saxena cpi->bus_id = cam_sim_bus(sim); 1299*2d1d418eSSumit Saxena /* 1300*2d1d418eSSumit Saxena * XXXSLM-I think this needs to change based on config page or 1301*2d1d418eSSumit Saxena * something instead of hardcoded to 150000. 1302*2d1d418eSSumit Saxena */ 1303*2d1d418eSSumit Saxena cpi->base_transfer_speed = 150000; 1304*2d1d418eSSumit Saxena cpi->transport = XPORT_SAS; 1305*2d1d418eSSumit Saxena cpi->transport_version = 0; 1306*2d1d418eSSumit Saxena cpi->protocol = PROTO_SCSI; 1307*2d1d418eSSumit Saxena cpi->protocol_version = SCSI_REV_SPC; 1308*2d1d418eSSumit Saxena 1309*2d1d418eSSumit Saxena targ = mpi3mr_find_target_by_per_id(cam_sc, ccb->ccb_h.target_id); 1310*2d1d418eSSumit Saxena 1311*2d1d418eSSumit Saxena if (targ && (targ->dev_type == MPI3_DEVICE_DEVFORM_PCIE) && 1312*2d1d418eSSumit Saxena ((targ->dev_spec.pcie_inf.dev_info & 1313*2d1d418eSSumit Saxena MPI3_DEVICE0_PCIE_DEVICE_INFO_TYPE_MASK) == 1314*2d1d418eSSumit Saxena MPI3_DEVICE0_PCIE_DEVICE_INFO_TYPE_NVME_DEVICE)) { 1315*2d1d418eSSumit Saxena cpi->maxio = targ->dev_spec.pcie_inf.mdts; 1316*2d1d418eSSumit Saxena mpi3mr_dprint(cam_sc->sc, MPI3MR_XINFO, 1317*2d1d418eSSumit Saxena "PCI device target_id: %u max io size: %u\n", 1318*2d1d418eSSumit Saxena ccb->ccb_h.target_id, cpi->maxio); 1319*2d1d418eSSumit Saxena } else { 1320*2d1d418eSSumit Saxena cpi->maxio = PAGE_SIZE * (MPI3MR_SG_DEPTH - 1); 1321*2d1d418eSSumit Saxena } 1322*2d1d418eSSumit Saxena mpi3mr_set_ccbstatus(ccb, CAM_REQ_CMP); 1323*2d1d418eSSumit Saxena break; 1324*2d1d418eSSumit Saxena } 1325*2d1d418eSSumit Saxena case XPT_GET_TRAN_SETTINGS: 1326*2d1d418eSSumit Saxena { 1327*2d1d418eSSumit Saxena struct ccb_trans_settings *cts; 1328*2d1d418eSSumit Saxena struct ccb_trans_settings_sas *sas; 1329*2d1d418eSSumit Saxena struct ccb_trans_settings_scsi *scsi; 1330*2d1d418eSSumit Saxena 1331*2d1d418eSSumit Saxena cts = &ccb->cts; 1332*2d1d418eSSumit Saxena sas = &cts->xport_specific.sas; 1333*2d1d418eSSumit Saxena scsi = &cts->proto_specific.scsi; 1334*2d1d418eSSumit Saxena 1335*2d1d418eSSumit Saxena KASSERT(cts->ccb_h.target_id < cam_sc->maxtargets, 1336*2d1d418eSSumit Saxena ("Target %d out of bounds in XPT_GET_TRAN_SETTINGS\n", 1337*2d1d418eSSumit Saxena cts->ccb_h.target_id)); 1338*2d1d418eSSumit Saxena targ = mpi3mr_find_target_by_per_id(cam_sc, cts->ccb_h.target_id); 1339*2d1d418eSSumit Saxena 1340*2d1d418eSSumit Saxena if (targ == NULL) { 1341*2d1d418eSSumit Saxena mpi3mr_dprint(cam_sc->sc, MPI3MR_TRACE, "Device with target ID: 0x%x does not exist\n", 1342*2d1d418eSSumit Saxena cts->ccb_h.target_id); 1343*2d1d418eSSumit Saxena mpi3mr_set_ccbstatus(ccb, CAM_DEV_NOT_THERE); 1344*2d1d418eSSumit Saxena break; 1345*2d1d418eSSumit Saxena } 1346*2d1d418eSSumit Saxena 1347*2d1d418eSSumit Saxena if ((targ->dev_handle == 0x0) || (targ->dev_removed == 1)) { 1348*2d1d418eSSumit Saxena mpi3mr_set_ccbstatus(ccb, CAM_DEV_NOT_THERE); 1349*2d1d418eSSumit Saxena break; 1350*2d1d418eSSumit Saxena } 1351*2d1d418eSSumit Saxena 1352*2d1d418eSSumit Saxena cts->protocol_version = SCSI_REV_SPC2; 1353*2d1d418eSSumit Saxena cts->transport = XPORT_SAS; 1354*2d1d418eSSumit Saxena cts->transport_version = 0; 1355*2d1d418eSSumit Saxena 1356*2d1d418eSSumit Saxena sas->valid = CTS_SAS_VALID_SPEED; 1357*2d1d418eSSumit Saxena 1358*2d1d418eSSumit Saxena switch (targ->link_rate) { 1359*2d1d418eSSumit Saxena case 0x08: 1360*2d1d418eSSumit Saxena sas->bitrate = 150000; 1361*2d1d418eSSumit Saxena break; 1362*2d1d418eSSumit Saxena case 0x09: 1363*2d1d418eSSumit Saxena sas->bitrate = 300000; 1364*2d1d418eSSumit Saxena break; 1365*2d1d418eSSumit Saxena case 0x0a: 1366*2d1d418eSSumit Saxena sas->bitrate = 600000; 1367*2d1d418eSSumit Saxena break; 1368*2d1d418eSSumit Saxena case 0x0b: 1369*2d1d418eSSumit Saxena sas->bitrate = 1200000; 1370*2d1d418eSSumit Saxena break; 1371*2d1d418eSSumit Saxena default: 1372*2d1d418eSSumit Saxena sas->valid = 0; 1373*2d1d418eSSumit Saxena } 1374*2d1d418eSSumit Saxena 1375*2d1d418eSSumit Saxena cts->protocol = PROTO_SCSI; 1376*2d1d418eSSumit Saxena scsi->valid = CTS_SCSI_VALID_TQ; 1377*2d1d418eSSumit Saxena scsi->flags = CTS_SCSI_FLAGS_TAG_ENB; 1378*2d1d418eSSumit Saxena 1379*2d1d418eSSumit Saxena mpi3mr_set_ccbstatus(ccb, CAM_REQ_CMP); 1380*2d1d418eSSumit Saxena break; 1381*2d1d418eSSumit Saxena } 1382*2d1d418eSSumit Saxena case XPT_CALC_GEOMETRY: 1383*2d1d418eSSumit Saxena cam_calc_geometry(&ccb->ccg, /*extended*/1); 1384*2d1d418eSSumit Saxena mpi3mr_set_ccbstatus(ccb, CAM_REQ_CMP); 1385*2d1d418eSSumit Saxena break; 1386*2d1d418eSSumit Saxena case XPT_RESET_DEV: 1387*2d1d418eSSumit Saxena mpi3mr_dprint(cam_sc->sc, MPI3MR_INFO, "mpi3mr_action " 1388*2d1d418eSSumit Saxena "XPT_RESET_DEV\n"); 1389*2d1d418eSSumit Saxena return; 1390*2d1d418eSSumit Saxena case XPT_RESET_BUS: 1391*2d1d418eSSumit Saxena case XPT_ABORT: 1392*2d1d418eSSumit Saxena case XPT_TERM_IO: 1393*2d1d418eSSumit Saxena mpi3mr_dprint(cam_sc->sc, MPI3MR_INFO, "mpi3mr_action faking success " 1394*2d1d418eSSumit Saxena "for abort or reset\n"); 1395*2d1d418eSSumit Saxena mpi3mr_set_ccbstatus(ccb, CAM_REQ_CMP); 1396*2d1d418eSSumit Saxena break; 1397*2d1d418eSSumit Saxena case XPT_SCSI_IO: 1398*2d1d418eSSumit Saxena mpi3mr_action_scsiio(cam_sc, ccb); 1399*2d1d418eSSumit Saxena return; 1400*2d1d418eSSumit Saxena default: 1401*2d1d418eSSumit Saxena mpi3mr_set_ccbstatus(ccb, CAM_FUNC_NOTAVAIL); 1402*2d1d418eSSumit Saxena break; 1403*2d1d418eSSumit Saxena } 1404*2d1d418eSSumit Saxena xpt_done(ccb); 1405*2d1d418eSSumit Saxena } 1406*2d1d418eSSumit Saxena 1407*2d1d418eSSumit Saxena void 1408*2d1d418eSSumit Saxena mpi3mr_startup_increment(struct mpi3mr_cam_softc *cam_sc) 1409*2d1d418eSSumit Saxena { 1410*2d1d418eSSumit Saxena if ((cam_sc->flags & MPI3MRSAS_IN_STARTUP) != 0) { 1411*2d1d418eSSumit Saxena if (cam_sc->startup_refcount++ == 0) { 1412*2d1d418eSSumit Saxena /* just starting, freeze the simq */ 1413*2d1d418eSSumit Saxena mpi3mr_dprint(cam_sc->sc, MPI3MR_XINFO, 1414*2d1d418eSSumit Saxena "%s freezing simq\n", __func__); 1415*2d1d418eSSumit Saxena xpt_hold_boot(); 1416*2d1d418eSSumit Saxena } 1417*2d1d418eSSumit Saxena mpi3mr_dprint(cam_sc->sc, MPI3MR_XINFO, "%s refcount %u\n", __func__, 1418*2d1d418eSSumit Saxena cam_sc->startup_refcount); 1419*2d1d418eSSumit Saxena } 1420*2d1d418eSSumit Saxena } 1421*2d1d418eSSumit Saxena 1422*2d1d418eSSumit Saxena void 1423*2d1d418eSSumit Saxena mpi3mr_release_simq_reinit(struct mpi3mr_cam_softc *cam_sc) 1424*2d1d418eSSumit Saxena { 1425*2d1d418eSSumit Saxena if (cam_sc->flags & MPI3MRSAS_QUEUE_FROZEN) { 1426*2d1d418eSSumit Saxena cam_sc->flags &= ~MPI3MRSAS_QUEUE_FROZEN; 1427*2d1d418eSSumit Saxena xpt_release_simq(cam_sc->sim, 1); 1428*2d1d418eSSumit Saxena mpi3mr_dprint(cam_sc->sc, MPI3MR_INFO, "Unfreezing SIM queue\n"); 1429*2d1d418eSSumit Saxena } 1430*2d1d418eSSumit Saxena } 1431*2d1d418eSSumit Saxena 1432*2d1d418eSSumit Saxena void 1433*2d1d418eSSumit Saxena mpi3mr_rescan_target(struct mpi3mr_softc *sc, struct mpi3mr_target *targ) 1434*2d1d418eSSumit Saxena { 1435*2d1d418eSSumit Saxena struct mpi3mr_cam_softc *cam_sc = sc->cam_sc; 1436*2d1d418eSSumit Saxena path_id_t pathid; 1437*2d1d418eSSumit Saxena target_id_t targetid; 1438*2d1d418eSSumit Saxena union ccb *ccb; 1439*2d1d418eSSumit Saxena 1440*2d1d418eSSumit Saxena pathid = cam_sim_path(cam_sc->sim); 1441*2d1d418eSSumit Saxena if (targ == NULL) 1442*2d1d418eSSumit Saxena targetid = CAM_TARGET_WILDCARD; 1443*2d1d418eSSumit Saxena else 1444*2d1d418eSSumit Saxena targetid = targ->per_id; 1445*2d1d418eSSumit Saxena 1446*2d1d418eSSumit Saxena /* 1447*2d1d418eSSumit Saxena * Allocate a CCB and schedule a rescan. 1448*2d1d418eSSumit Saxena */ 1449*2d1d418eSSumit Saxena ccb = xpt_alloc_ccb_nowait(); 1450*2d1d418eSSumit Saxena if (ccb == NULL) { 1451*2d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_ERROR, "unable to alloc CCB for rescan\n"); 1452*2d1d418eSSumit Saxena return; 1453*2d1d418eSSumit Saxena } 1454*2d1d418eSSumit Saxena 1455*2d1d418eSSumit Saxena if (xpt_create_path(&ccb->ccb_h.path, NULL, pathid, targetid, 1456*2d1d418eSSumit Saxena CAM_LUN_WILDCARD) != CAM_REQ_CMP) { 1457*2d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_ERROR, "unable to create path for rescan\n"); 1458*2d1d418eSSumit Saxena xpt_free_ccb(ccb); 1459*2d1d418eSSumit Saxena return; 1460*2d1d418eSSumit Saxena } 1461*2d1d418eSSumit Saxena 1462*2d1d418eSSumit Saxena if (targetid == CAM_TARGET_WILDCARD) 1463*2d1d418eSSumit Saxena ccb->ccb_h.func_code = XPT_SCAN_BUS; 1464*2d1d418eSSumit Saxena else 1465*2d1d418eSSumit Saxena ccb->ccb_h.func_code = XPT_SCAN_TGT; 1466*2d1d418eSSumit Saxena 1467*2d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_EVENT, "%s target id 0x%x\n", __func__, targetid); 1468*2d1d418eSSumit Saxena xpt_rescan(ccb); 1469*2d1d418eSSumit Saxena } 1470*2d1d418eSSumit Saxena 1471*2d1d418eSSumit Saxena void 1472*2d1d418eSSumit Saxena mpi3mr_startup_decrement(struct mpi3mr_cam_softc *cam_sc) 1473*2d1d418eSSumit Saxena { 1474*2d1d418eSSumit Saxena if ((cam_sc->flags & MPI3MRSAS_IN_STARTUP) != 0) { 1475*2d1d418eSSumit Saxena if (--cam_sc->startup_refcount == 0) { 1476*2d1d418eSSumit Saxena /* finished all discovery-related actions, release 1477*2d1d418eSSumit Saxena * the simq and rescan for the latest topology. 1478*2d1d418eSSumit Saxena */ 1479*2d1d418eSSumit Saxena mpi3mr_dprint(cam_sc->sc, MPI3MR_XINFO, 1480*2d1d418eSSumit Saxena "%s releasing simq\n", __func__); 1481*2d1d418eSSumit Saxena cam_sc->flags &= ~MPI3MRSAS_IN_STARTUP; 1482*2d1d418eSSumit Saxena xpt_release_simq(cam_sc->sim, 1); 1483*2d1d418eSSumit Saxena xpt_release_boot(); 1484*2d1d418eSSumit Saxena } 1485*2d1d418eSSumit Saxena mpi3mr_dprint(cam_sc->sc, MPI3MR_XINFO, "%s refcount %u\n", __func__, 1486*2d1d418eSSumit Saxena cam_sc->startup_refcount); 1487*2d1d418eSSumit Saxena } 1488*2d1d418eSSumit Saxena } 1489*2d1d418eSSumit Saxena 1490*2d1d418eSSumit Saxena static void 1491*2d1d418eSSumit Saxena mpi3mr_fw_event_free(struct mpi3mr_softc *sc, struct mpi3mr_fw_event_work *fw_event) 1492*2d1d418eSSumit Saxena { 1493*2d1d418eSSumit Saxena if (!fw_event) 1494*2d1d418eSSumit Saxena return; 1495*2d1d418eSSumit Saxena 1496*2d1d418eSSumit Saxena if (fw_event->event_data != NULL) { 1497*2d1d418eSSumit Saxena free(fw_event->event_data, M_MPI3MR); 1498*2d1d418eSSumit Saxena fw_event->event_data = NULL; 1499*2d1d418eSSumit Saxena } 1500*2d1d418eSSumit Saxena 1501*2d1d418eSSumit Saxena free(fw_event, M_MPI3MR); 1502*2d1d418eSSumit Saxena fw_event = NULL; 1503*2d1d418eSSumit Saxena } 1504*2d1d418eSSumit Saxena 1505*2d1d418eSSumit Saxena static void 1506*2d1d418eSSumit Saxena mpi3mr_freeup_events(struct mpi3mr_softc *sc) 1507*2d1d418eSSumit Saxena { 1508*2d1d418eSSumit Saxena struct mpi3mr_fw_event_work *fw_event = NULL; 1509*2d1d418eSSumit Saxena mtx_lock(&sc->mpi3mr_mtx); 1510*2d1d418eSSumit Saxena while ((fw_event = TAILQ_FIRST(&sc->cam_sc->ev_queue)) != NULL) { 1511*2d1d418eSSumit Saxena TAILQ_REMOVE(&sc->cam_sc->ev_queue, fw_event, ev_link); 1512*2d1d418eSSumit Saxena mpi3mr_fw_event_free(sc, fw_event); 1513*2d1d418eSSumit Saxena } 1514*2d1d418eSSumit Saxena mtx_unlock(&sc->mpi3mr_mtx); 1515*2d1d418eSSumit Saxena } 1516*2d1d418eSSumit Saxena 1517*2d1d418eSSumit Saxena static void 1518*2d1d418eSSumit Saxena mpi3mr_sastopochg_evt_debug(struct mpi3mr_softc *sc, 1519*2d1d418eSSumit Saxena Mpi3EventDataSasTopologyChangeList_t *event_data) 1520*2d1d418eSSumit Saxena { 1521*2d1d418eSSumit Saxena int i; 1522*2d1d418eSSumit Saxena U16 handle; 1523*2d1d418eSSumit Saxena U8 reason_code, phy_number; 1524*2d1d418eSSumit Saxena char *status_str = NULL; 1525*2d1d418eSSumit Saxena U8 link_rate, prev_link_rate; 1526*2d1d418eSSumit Saxena 1527*2d1d418eSSumit Saxena switch (event_data->ExpStatus) { 1528*2d1d418eSSumit Saxena case MPI3_EVENT_SAS_TOPO_ES_NOT_RESPONDING: 1529*2d1d418eSSumit Saxena status_str = "remove"; 1530*2d1d418eSSumit Saxena break; 1531*2d1d418eSSumit Saxena case MPI3_EVENT_SAS_TOPO_ES_RESPONDING: 1532*2d1d418eSSumit Saxena status_str = "responding"; 1533*2d1d418eSSumit Saxena break; 1534*2d1d418eSSumit Saxena case MPI3_EVENT_SAS_TOPO_ES_DELAY_NOT_RESPONDING: 1535*2d1d418eSSumit Saxena status_str = "remove delay"; 1536*2d1d418eSSumit Saxena break; 1537*2d1d418eSSumit Saxena case MPI3_EVENT_SAS_TOPO_ES_NO_EXPANDER: 1538*2d1d418eSSumit Saxena status_str = "direct attached"; 1539*2d1d418eSSumit Saxena break; 1540*2d1d418eSSumit Saxena default: 1541*2d1d418eSSumit Saxena status_str = "unknown status"; 1542*2d1d418eSSumit Saxena break; 1543*2d1d418eSSumit Saxena } 1544*2d1d418eSSumit Saxena 1545*2d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_INFO, "%s :sas topology change: (%s)\n", 1546*2d1d418eSSumit Saxena __func__, status_str); 1547*2d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_INFO, 1548*2d1d418eSSumit Saxena "%s :\texpander_handle(0x%04x), enclosure_handle(0x%04x) " 1549*2d1d418eSSumit Saxena "start_phy(%02d), num_entries(%d)\n", __func__, 1550*2d1d418eSSumit Saxena (event_data->ExpanderDevHandle), 1551*2d1d418eSSumit Saxena (event_data->EnclosureHandle), 1552*2d1d418eSSumit Saxena event_data->StartPhyNum, event_data->NumEntries); 1553*2d1d418eSSumit Saxena for (i = 0; i < event_data->NumEntries; i++) { 1554*2d1d418eSSumit Saxena handle = (event_data->PhyEntry[i].AttachedDevHandle); 1555*2d1d418eSSumit Saxena if (!handle) 1556*2d1d418eSSumit Saxena continue; 1557*2d1d418eSSumit Saxena phy_number = event_data->StartPhyNum + i; 1558*2d1d418eSSumit Saxena reason_code = event_data->PhyEntry[i].Status & 1559*2d1d418eSSumit Saxena MPI3_EVENT_SAS_TOPO_PHY_RC_MASK; 1560*2d1d418eSSumit Saxena switch (reason_code) { 1561*2d1d418eSSumit Saxena case MPI3_EVENT_SAS_TOPO_PHY_RC_TARG_NOT_RESPONDING: 1562*2d1d418eSSumit Saxena status_str = "target remove"; 1563*2d1d418eSSumit Saxena break; 1564*2d1d418eSSumit Saxena case MPI3_EVENT_SAS_TOPO_PHY_RC_DELAY_NOT_RESPONDING: 1565*2d1d418eSSumit Saxena status_str = "delay target remove"; 1566*2d1d418eSSumit Saxena break; 1567*2d1d418eSSumit Saxena case MPI3_EVENT_SAS_TOPO_PHY_RC_PHY_CHANGED: 1568*2d1d418eSSumit Saxena status_str = "link rate change"; 1569*2d1d418eSSumit Saxena break; 1570*2d1d418eSSumit Saxena case MPI3_EVENT_SAS_TOPO_PHY_RC_NO_CHANGE: 1571*2d1d418eSSumit Saxena status_str = "target responding"; 1572*2d1d418eSSumit Saxena break; 1573*2d1d418eSSumit Saxena default: 1574*2d1d418eSSumit Saxena status_str = "unknown"; 1575*2d1d418eSSumit Saxena break; 1576*2d1d418eSSumit Saxena } 1577*2d1d418eSSumit Saxena link_rate = event_data->PhyEntry[i].LinkRate >> 4; 1578*2d1d418eSSumit Saxena prev_link_rate = event_data->PhyEntry[i].LinkRate & 0xF; 1579*2d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_INFO, "%s :\tphy(%02d), attached_handle(0x%04x): %s:" 1580*2d1d418eSSumit Saxena " link rate: new(0x%02x), old(0x%02x)\n", __func__, 1581*2d1d418eSSumit Saxena phy_number, handle, status_str, link_rate, prev_link_rate); 1582*2d1d418eSSumit Saxena } 1583*2d1d418eSSumit Saxena } 1584*2d1d418eSSumit Saxena 1585*2d1d418eSSumit Saxena static void 1586*2d1d418eSSumit Saxena mpi3mr_process_sastopochg_evt(struct mpi3mr_softc *sc, struct mpi3mr_fw_event_work *fwevt) 1587*2d1d418eSSumit Saxena { 1588*2d1d418eSSumit Saxena 1589*2d1d418eSSumit Saxena Mpi3EventDataSasTopologyChangeList_t *event_data = 1590*2d1d418eSSumit Saxena (Mpi3EventDataSasTopologyChangeList_t *)fwevt->event_data; 1591*2d1d418eSSumit Saxena int i; 1592*2d1d418eSSumit Saxena U16 handle; 1593*2d1d418eSSumit Saxena U8 reason_code, link_rate; 1594*2d1d418eSSumit Saxena struct mpi3mr_target *target = NULL; 1595*2d1d418eSSumit Saxena 1596*2d1d418eSSumit Saxena 1597*2d1d418eSSumit Saxena mpi3mr_sastopochg_evt_debug(sc, event_data); 1598*2d1d418eSSumit Saxena 1599*2d1d418eSSumit Saxena for (i = 0; i < event_data->NumEntries; i++) { 1600*2d1d418eSSumit Saxena handle = le16toh(event_data->PhyEntry[i].AttachedDevHandle); 1601*2d1d418eSSumit Saxena link_rate = event_data->PhyEntry[i].LinkRate >> 4; 1602*2d1d418eSSumit Saxena 1603*2d1d418eSSumit Saxena if (!handle) 1604*2d1d418eSSumit Saxena continue; 1605*2d1d418eSSumit Saxena target = mpi3mr_find_target_by_dev_handle(sc->cam_sc, handle); 1606*2d1d418eSSumit Saxena 1607*2d1d418eSSumit Saxena if (!target) 1608*2d1d418eSSumit Saxena continue; 1609*2d1d418eSSumit Saxena 1610*2d1d418eSSumit Saxena target->link_rate = link_rate; 1611*2d1d418eSSumit Saxena reason_code = event_data->PhyEntry[i].Status & 1612*2d1d418eSSumit Saxena MPI3_EVENT_SAS_TOPO_PHY_RC_MASK; 1613*2d1d418eSSumit Saxena 1614*2d1d418eSSumit Saxena switch (reason_code) { 1615*2d1d418eSSumit Saxena case MPI3_EVENT_SAS_TOPO_PHY_RC_TARG_NOT_RESPONDING: 1616*2d1d418eSSumit Saxena if (target->exposed_to_os) 1617*2d1d418eSSumit Saxena mpi3mr_remove_device_from_os(sc, target->dev_handle); 1618*2d1d418eSSumit Saxena mpi3mr_remove_device_from_list(sc, target, false); 1619*2d1d418eSSumit Saxena break; 1620*2d1d418eSSumit Saxena case MPI3_EVENT_SAS_TOPO_PHY_RC_PHY_CHANGED: 1621*2d1d418eSSumit Saxena break; 1622*2d1d418eSSumit Saxena default: 1623*2d1d418eSSumit Saxena break; 1624*2d1d418eSSumit Saxena } 1625*2d1d418eSSumit Saxena } 1626*2d1d418eSSumit Saxena 1627*2d1d418eSSumit Saxena /* 1628*2d1d418eSSumit Saxena * refcount was incremented for this event in 1629*2d1d418eSSumit Saxena * mpi3mr_evt_handler. Decrement it here because the event has 1630*2d1d418eSSumit Saxena * been processed. 1631*2d1d418eSSumit Saxena */ 1632*2d1d418eSSumit Saxena mpi3mr_startup_decrement(sc->cam_sc); 1633*2d1d418eSSumit Saxena return; 1634*2d1d418eSSumit Saxena } 1635*2d1d418eSSumit Saxena 1636*2d1d418eSSumit Saxena static inline void 1637*2d1d418eSSumit Saxena mpi3mr_logdata_evt_bh(struct mpi3mr_softc *sc, 1638*2d1d418eSSumit Saxena struct mpi3mr_fw_event_work *fwevt) 1639*2d1d418eSSumit Saxena { 1640*2d1d418eSSumit Saxena mpi3mr_app_save_logdata(sc, fwevt->event_data, 1641*2d1d418eSSumit Saxena fwevt->event_data_size); 1642*2d1d418eSSumit Saxena } 1643*2d1d418eSSumit Saxena 1644*2d1d418eSSumit Saxena static void 1645*2d1d418eSSumit Saxena mpi3mr_pcietopochg_evt_debug(struct mpi3mr_softc *sc, 1646*2d1d418eSSumit Saxena Mpi3EventDataPcieTopologyChangeList_t *event_data) 1647*2d1d418eSSumit Saxena { 1648*2d1d418eSSumit Saxena int i; 1649*2d1d418eSSumit Saxena U16 handle; 1650*2d1d418eSSumit Saxena U16 reason_code; 1651*2d1d418eSSumit Saxena U8 port_number; 1652*2d1d418eSSumit Saxena char *status_str = NULL; 1653*2d1d418eSSumit Saxena U8 link_rate, prev_link_rate; 1654*2d1d418eSSumit Saxena 1655*2d1d418eSSumit Saxena switch (event_data->SwitchStatus) { 1656*2d1d418eSSumit Saxena case MPI3_EVENT_PCIE_TOPO_SS_NOT_RESPONDING: 1657*2d1d418eSSumit Saxena status_str = "remove"; 1658*2d1d418eSSumit Saxena break; 1659*2d1d418eSSumit Saxena case MPI3_EVENT_PCIE_TOPO_SS_RESPONDING: 1660*2d1d418eSSumit Saxena status_str = "responding"; 1661*2d1d418eSSumit Saxena break; 1662*2d1d418eSSumit Saxena case MPI3_EVENT_PCIE_TOPO_SS_DELAY_NOT_RESPONDING: 1663*2d1d418eSSumit Saxena status_str = "remove delay"; 1664*2d1d418eSSumit Saxena break; 1665*2d1d418eSSumit Saxena case MPI3_EVENT_PCIE_TOPO_SS_NO_PCIE_SWITCH: 1666*2d1d418eSSumit Saxena status_str = "direct attached"; 1667*2d1d418eSSumit Saxena break; 1668*2d1d418eSSumit Saxena default: 1669*2d1d418eSSumit Saxena status_str = "unknown status"; 1670*2d1d418eSSumit Saxena break; 1671*2d1d418eSSumit Saxena } 1672*2d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_INFO, "%s :pcie topology change: (%s)\n", 1673*2d1d418eSSumit Saxena __func__, status_str); 1674*2d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_INFO, 1675*2d1d418eSSumit Saxena "%s :\tswitch_handle(0x%04x), enclosure_handle(0x%04x)" 1676*2d1d418eSSumit Saxena "start_port(%02d), num_entries(%d)\n", __func__, 1677*2d1d418eSSumit Saxena le16toh(event_data->SwitchDevHandle), 1678*2d1d418eSSumit Saxena le16toh(event_data->EnclosureHandle), 1679*2d1d418eSSumit Saxena event_data->StartPortNum, event_data->NumEntries); 1680*2d1d418eSSumit Saxena for (i = 0; i < event_data->NumEntries; i++) { 1681*2d1d418eSSumit Saxena handle = 1682*2d1d418eSSumit Saxena le16toh(event_data->PortEntry[i].AttachedDevHandle); 1683*2d1d418eSSumit Saxena if (!handle) 1684*2d1d418eSSumit Saxena continue; 1685*2d1d418eSSumit Saxena port_number = event_data->StartPortNum + i; 1686*2d1d418eSSumit Saxena reason_code = event_data->PortEntry[i].PortStatus; 1687*2d1d418eSSumit Saxena switch (reason_code) { 1688*2d1d418eSSumit Saxena case MPI3_EVENT_PCIE_TOPO_PS_NOT_RESPONDING: 1689*2d1d418eSSumit Saxena status_str = "target remove"; 1690*2d1d418eSSumit Saxena break; 1691*2d1d418eSSumit Saxena case MPI3_EVENT_PCIE_TOPO_PS_DELAY_NOT_RESPONDING: 1692*2d1d418eSSumit Saxena status_str = "delay target remove"; 1693*2d1d418eSSumit Saxena break; 1694*2d1d418eSSumit Saxena case MPI3_EVENT_PCIE_TOPO_PS_PORT_CHANGED: 1695*2d1d418eSSumit Saxena status_str = "link rate change"; 1696*2d1d418eSSumit Saxena break; 1697*2d1d418eSSumit Saxena case MPI3_EVENT_PCIE_TOPO_PS_NO_CHANGE: 1698*2d1d418eSSumit Saxena status_str = "target responding"; 1699*2d1d418eSSumit Saxena break; 1700*2d1d418eSSumit Saxena default: 1701*2d1d418eSSumit Saxena status_str = "unknown"; 1702*2d1d418eSSumit Saxena break; 1703*2d1d418eSSumit Saxena } 1704*2d1d418eSSumit Saxena link_rate = event_data->PortEntry[i].CurrentPortInfo & 1705*2d1d418eSSumit Saxena MPI3_EVENT_PCIE_TOPO_PI_RATE_MASK; 1706*2d1d418eSSumit Saxena prev_link_rate = event_data->PortEntry[i].PreviousPortInfo & 1707*2d1d418eSSumit Saxena MPI3_EVENT_PCIE_TOPO_PI_RATE_MASK; 1708*2d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_INFO, "%s :\tport(%02d), attached_handle(0x%04x): %s:" 1709*2d1d418eSSumit Saxena " link rate: new(0x%02x), old(0x%02x)\n", __func__, 1710*2d1d418eSSumit Saxena port_number, handle, status_str, link_rate, prev_link_rate); 1711*2d1d418eSSumit Saxena } 1712*2d1d418eSSumit Saxena } 1713*2d1d418eSSumit Saxena 1714*2d1d418eSSumit Saxena static void mpi3mr_process_pcietopochg_evt(struct mpi3mr_softc *sc, 1715*2d1d418eSSumit Saxena struct mpi3mr_fw_event_work *fwevt) 1716*2d1d418eSSumit Saxena { 1717*2d1d418eSSumit Saxena Mpi3EventDataPcieTopologyChangeList_t *event_data = 1718*2d1d418eSSumit Saxena (Mpi3EventDataPcieTopologyChangeList_t *)fwevt->event_data; 1719*2d1d418eSSumit Saxena int i; 1720*2d1d418eSSumit Saxena U16 handle; 1721*2d1d418eSSumit Saxena U8 reason_code, link_rate; 1722*2d1d418eSSumit Saxena struct mpi3mr_target *target = NULL; 1723*2d1d418eSSumit Saxena 1724*2d1d418eSSumit Saxena 1725*2d1d418eSSumit Saxena mpi3mr_pcietopochg_evt_debug(sc, event_data); 1726*2d1d418eSSumit Saxena 1727*2d1d418eSSumit Saxena for (i = 0; i < event_data->NumEntries; i++) { 1728*2d1d418eSSumit Saxena handle = 1729*2d1d418eSSumit Saxena le16toh(event_data->PortEntry[i].AttachedDevHandle); 1730*2d1d418eSSumit Saxena if (!handle) 1731*2d1d418eSSumit Saxena continue; 1732*2d1d418eSSumit Saxena target = mpi3mr_find_target_by_dev_handle(sc->cam_sc, handle); 1733*2d1d418eSSumit Saxena if (!target) 1734*2d1d418eSSumit Saxena continue; 1735*2d1d418eSSumit Saxena 1736*2d1d418eSSumit Saxena link_rate = event_data->PortEntry[i].CurrentPortInfo & 1737*2d1d418eSSumit Saxena MPI3_EVENT_PCIE_TOPO_PI_RATE_MASK; 1738*2d1d418eSSumit Saxena target->link_rate = link_rate; 1739*2d1d418eSSumit Saxena 1740*2d1d418eSSumit Saxena reason_code = event_data->PortEntry[i].PortStatus; 1741*2d1d418eSSumit Saxena 1742*2d1d418eSSumit Saxena switch (reason_code) { 1743*2d1d418eSSumit Saxena case MPI3_EVENT_PCIE_TOPO_PS_NOT_RESPONDING: 1744*2d1d418eSSumit Saxena if (target->exposed_to_os) 1745*2d1d418eSSumit Saxena mpi3mr_remove_device_from_os(sc, target->dev_handle); 1746*2d1d418eSSumit Saxena mpi3mr_remove_device_from_list(sc, target, false); 1747*2d1d418eSSumit Saxena break; 1748*2d1d418eSSumit Saxena case MPI3_EVENT_PCIE_TOPO_PS_PORT_CHANGED: 1749*2d1d418eSSumit Saxena break; 1750*2d1d418eSSumit Saxena default: 1751*2d1d418eSSumit Saxena break; 1752*2d1d418eSSumit Saxena } 1753*2d1d418eSSumit Saxena } 1754*2d1d418eSSumit Saxena 1755*2d1d418eSSumit Saxena /* 1756*2d1d418eSSumit Saxena * refcount was incremented for this event in 1757*2d1d418eSSumit Saxena * mpi3mr_evt_handler. Decrement it here because the event has 1758*2d1d418eSSumit Saxena * been processed. 1759*2d1d418eSSumit Saxena */ 1760*2d1d418eSSumit Saxena mpi3mr_startup_decrement(sc->cam_sc); 1761*2d1d418eSSumit Saxena return; 1762*2d1d418eSSumit Saxena } 1763*2d1d418eSSumit Saxena 1764*2d1d418eSSumit Saxena void mpi3mr_add_device(struct mpi3mr_softc *sc, U16 per_id) 1765*2d1d418eSSumit Saxena { 1766*2d1d418eSSumit Saxena struct mpi3mr_target *target; 1767*2d1d418eSSumit Saxena 1768*2d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_EVENT, 1769*2d1d418eSSumit Saxena "Adding device(persistent id: 0x%x)\n", per_id); 1770*2d1d418eSSumit Saxena 1771*2d1d418eSSumit Saxena mpi3mr_startup_increment(sc->cam_sc); 1772*2d1d418eSSumit Saxena target = mpi3mr_find_target_by_per_id(sc->cam_sc, per_id); 1773*2d1d418eSSumit Saxena 1774*2d1d418eSSumit Saxena if (!target) { 1775*2d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_INFO, "Not available in driver's" 1776*2d1d418eSSumit Saxena "internal target list, persistent_id: %d\n", 1777*2d1d418eSSumit Saxena per_id); 1778*2d1d418eSSumit Saxena goto out; 1779*2d1d418eSSumit Saxena } 1780*2d1d418eSSumit Saxena 1781*2d1d418eSSumit Saxena if (target->is_hidden) { 1782*2d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_EVENT, "Target is hidden, persistent_id: %d\n", 1783*2d1d418eSSumit Saxena per_id); 1784*2d1d418eSSumit Saxena goto out; 1785*2d1d418eSSumit Saxena } 1786*2d1d418eSSumit Saxena 1787*2d1d418eSSumit Saxena if (!target->exposed_to_os && !sc->reset_in_progress) { 1788*2d1d418eSSumit Saxena mpi3mr_rescan_target(sc, target); 1789*2d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_INFO, 1790*2d1d418eSSumit Saxena "Added device persistent_id: %d dev_handle: %d\n", per_id, target->dev_handle); 1791*2d1d418eSSumit Saxena target->exposed_to_os = 1; 1792*2d1d418eSSumit Saxena } 1793*2d1d418eSSumit Saxena 1794*2d1d418eSSumit Saxena out: 1795*2d1d418eSSumit Saxena mpi3mr_startup_decrement(sc->cam_sc); 1796*2d1d418eSSumit Saxena } 1797*2d1d418eSSumit Saxena 1798*2d1d418eSSumit Saxena int mpi3mr_remove_device_from_os(struct mpi3mr_softc *sc, U16 handle) 1799*2d1d418eSSumit Saxena { 1800*2d1d418eSSumit Saxena U32 i = 0; 1801*2d1d418eSSumit Saxena int retval = 0; 1802*2d1d418eSSumit Saxena struct mpi3mr_target *target; 1803*2d1d418eSSumit Saxena 1804*2d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_EVENT, 1805*2d1d418eSSumit Saxena "Removing Device (dev_handle: %d)\n", handle); 1806*2d1d418eSSumit Saxena 1807*2d1d418eSSumit Saxena target = mpi3mr_find_target_by_dev_handle(sc->cam_sc, handle); 1808*2d1d418eSSumit Saxena 1809*2d1d418eSSumit Saxena if (!target) { 1810*2d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_INFO, 1811*2d1d418eSSumit Saxena "Device (persistent_id: %d dev_handle: %d) is already removed from driver's list\n", 1812*2d1d418eSSumit Saxena target->per_id, handle); 1813*2d1d418eSSumit Saxena mpi3mr_rescan_target(sc, NULL); 1814*2d1d418eSSumit Saxena retval = -1; 1815*2d1d418eSSumit Saxena goto out; 1816*2d1d418eSSumit Saxena } 1817*2d1d418eSSumit Saxena 1818*2d1d418eSSumit Saxena target->flags |= MPI3MRSAS_TARGET_INREMOVAL; 1819*2d1d418eSSumit Saxena 1820*2d1d418eSSumit Saxena while (mpi3mr_atomic_read(&target->outstanding) && (i < 30)) { 1821*2d1d418eSSumit Saxena i++; 1822*2d1d418eSSumit Saxena if (!(i % 2)) { 1823*2d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_INFO, 1824*2d1d418eSSumit Saxena "[%2d]waiting for " 1825*2d1d418eSSumit Saxena "waiting for outstanding commands to complete on target: %d\n", 1826*2d1d418eSSumit Saxena i, target->per_id); 1827*2d1d418eSSumit Saxena } 1828*2d1d418eSSumit Saxena DELAY(1000 * 1000); 1829*2d1d418eSSumit Saxena } 1830*2d1d418eSSumit Saxena 1831*2d1d418eSSumit Saxena if (target->exposed_to_os && !sc->reset_in_progress) { 1832*2d1d418eSSumit Saxena mpi3mr_rescan_target(sc, target); 1833*2d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_INFO, 1834*2d1d418eSSumit Saxena "Removed device(persistent_id: %d dev_handle: %d)\n", target->per_id, handle); 1835*2d1d418eSSumit Saxena target->exposed_to_os = 0; 1836*2d1d418eSSumit Saxena } 1837*2d1d418eSSumit Saxena 1838*2d1d418eSSumit Saxena target->flags &= ~MPI3MRSAS_TARGET_INREMOVAL; 1839*2d1d418eSSumit Saxena out: 1840*2d1d418eSSumit Saxena return retval; 1841*2d1d418eSSumit Saxena } 1842*2d1d418eSSumit Saxena 1843*2d1d418eSSumit Saxena void mpi3mr_remove_device_from_list(struct mpi3mr_softc *sc, 1844*2d1d418eSSumit Saxena struct mpi3mr_target *target, bool must_delete) 1845*2d1d418eSSumit Saxena { 1846*2d1d418eSSumit Saxena mtx_lock_spin(&sc->target_lock); 1847*2d1d418eSSumit Saxena if ((target->state == MPI3MR_DEV_REMOVE_HS_STARTED) || 1848*2d1d418eSSumit Saxena (must_delete == true)) { 1849*2d1d418eSSumit Saxena TAILQ_REMOVE(&sc->cam_sc->tgt_list, target, tgt_next); 1850*2d1d418eSSumit Saxena target->state = MPI3MR_DEV_DELETED; 1851*2d1d418eSSumit Saxena } 1852*2d1d418eSSumit Saxena mtx_unlock_spin(&sc->target_lock); 1853*2d1d418eSSumit Saxena 1854*2d1d418eSSumit Saxena if (target->state == MPI3MR_DEV_DELETED) { 1855*2d1d418eSSumit Saxena free(target, M_MPI3MR); 1856*2d1d418eSSumit Saxena target = NULL; 1857*2d1d418eSSumit Saxena } 1858*2d1d418eSSumit Saxena 1859*2d1d418eSSumit Saxena return; 1860*2d1d418eSSumit Saxena } 1861*2d1d418eSSumit Saxena 1862*2d1d418eSSumit Saxena /** 1863*2d1d418eSSumit Saxena * mpi3mr_devstatuschg_evt_bh - DevStatusChange evt bottomhalf 1864*2d1d418eSSumit Saxena * @sc: Adapter instance reference 1865*2d1d418eSSumit Saxena * @fwevt: Firmware event 1866*2d1d418eSSumit Saxena * 1867*2d1d418eSSumit Saxena * Process Device Status Change event and based on device's new 1868*2d1d418eSSumit Saxena * information, either expose the device to the upper layers, or 1869*2d1d418eSSumit Saxena * remove the device from upper layers. 1870*2d1d418eSSumit Saxena * 1871*2d1d418eSSumit Saxena * Return: Nothing. 1872*2d1d418eSSumit Saxena */ 1873*2d1d418eSSumit Saxena static void mpi3mr_devstatuschg_evt_bh(struct mpi3mr_softc *sc, 1874*2d1d418eSSumit Saxena struct mpi3mr_fw_event_work *fwevt) 1875*2d1d418eSSumit Saxena { 1876*2d1d418eSSumit Saxena U16 dev_handle = 0; 1877*2d1d418eSSumit Saxena U8 uhide = 0, delete = 0, cleanup = 0; 1878*2d1d418eSSumit Saxena struct mpi3mr_target *tgtdev = NULL; 1879*2d1d418eSSumit Saxena Mpi3EventDataDeviceStatusChange_t *evtdata = 1880*2d1d418eSSumit Saxena (Mpi3EventDataDeviceStatusChange_t *)fwevt->event_data; 1881*2d1d418eSSumit Saxena 1882*2d1d418eSSumit Saxena 1883*2d1d418eSSumit Saxena 1884*2d1d418eSSumit Saxena dev_handle = le16toh(evtdata->DevHandle); 1885*2d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_INFO, 1886*2d1d418eSSumit Saxena "%s :device status change: handle(0x%04x): reason code(0x%x)\n", 1887*2d1d418eSSumit Saxena __func__, dev_handle, evtdata->ReasonCode); 1888*2d1d418eSSumit Saxena switch (evtdata->ReasonCode) { 1889*2d1d418eSSumit Saxena case MPI3_EVENT_DEV_STAT_RC_HIDDEN: 1890*2d1d418eSSumit Saxena delete = 1; 1891*2d1d418eSSumit Saxena break; 1892*2d1d418eSSumit Saxena case MPI3_EVENT_DEV_STAT_RC_NOT_HIDDEN: 1893*2d1d418eSSumit Saxena uhide = 1; 1894*2d1d418eSSumit Saxena break; 1895*2d1d418eSSumit Saxena case MPI3_EVENT_DEV_STAT_RC_VD_NOT_RESPONDING: 1896*2d1d418eSSumit Saxena delete = 1; 1897*2d1d418eSSumit Saxena cleanup = 1; 1898*2d1d418eSSumit Saxena break; 1899*2d1d418eSSumit Saxena default: 1900*2d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_INFO, "%s :Unhandled reason code(0x%x)\n", __func__, 1901*2d1d418eSSumit Saxena evtdata->ReasonCode); 1902*2d1d418eSSumit Saxena break; 1903*2d1d418eSSumit Saxena } 1904*2d1d418eSSumit Saxena 1905*2d1d418eSSumit Saxena tgtdev = mpi3mr_find_target_by_dev_handle(sc->cam_sc, dev_handle); 1906*2d1d418eSSumit Saxena if (!tgtdev) 1907*2d1d418eSSumit Saxena return; 1908*2d1d418eSSumit Saxena 1909*2d1d418eSSumit Saxena if (uhide) { 1910*2d1d418eSSumit Saxena if (!tgtdev->exposed_to_os) 1911*2d1d418eSSumit Saxena mpi3mr_add_device(sc, tgtdev->per_id); 1912*2d1d418eSSumit Saxena } 1913*2d1d418eSSumit Saxena 1914*2d1d418eSSumit Saxena if (delete) 1915*2d1d418eSSumit Saxena mpi3mr_remove_device_from_os(sc, dev_handle); 1916*2d1d418eSSumit Saxena 1917*2d1d418eSSumit Saxena if (cleanup) 1918*2d1d418eSSumit Saxena mpi3mr_remove_device_from_list(sc, tgtdev, false); 1919*2d1d418eSSumit Saxena } 1920*2d1d418eSSumit Saxena 1921*2d1d418eSSumit Saxena /** 1922*2d1d418eSSumit Saxena * mpi3mr_devinfochg_evt_bh - DeviceInfoChange evt bottomhalf 1923*2d1d418eSSumit Saxena * @sc: Adapter instance reference 1924*2d1d418eSSumit Saxena * @dev_pg0: New device page0 1925*2d1d418eSSumit Saxena * 1926*2d1d418eSSumit Saxena * Process Device Info Change event and based on device's new 1927*2d1d418eSSumit Saxena * information, either expose the device to the upper layers, or 1928*2d1d418eSSumit Saxena * remove the device from upper layers or update the details of 1929*2d1d418eSSumit Saxena * the device. 1930*2d1d418eSSumit Saxena * 1931*2d1d418eSSumit Saxena * Return: Nothing. 1932*2d1d418eSSumit Saxena */ 1933*2d1d418eSSumit Saxena static void mpi3mr_devinfochg_evt_bh(struct mpi3mr_softc *sc, 1934*2d1d418eSSumit Saxena Mpi3DevicePage0_t *dev_pg0) 1935*2d1d418eSSumit Saxena { 1936*2d1d418eSSumit Saxena struct mpi3mr_target *tgtdev = NULL; 1937*2d1d418eSSumit Saxena U16 dev_handle = 0, perst_id = 0; 1938*2d1d418eSSumit Saxena 1939*2d1d418eSSumit Saxena perst_id = le16toh(dev_pg0->PersistentID); 1940*2d1d418eSSumit Saxena dev_handle = le16toh(dev_pg0->DevHandle); 1941*2d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_INFO, 1942*2d1d418eSSumit Saxena "%s :Device info change: handle(0x%04x): persist_id(0x%x)\n", 1943*2d1d418eSSumit Saxena __func__, dev_handle, perst_id); 1944*2d1d418eSSumit Saxena tgtdev = mpi3mr_find_target_by_dev_handle(sc->cam_sc, dev_handle); 1945*2d1d418eSSumit Saxena if (!tgtdev) 1946*2d1d418eSSumit Saxena return; 1947*2d1d418eSSumit Saxena 1948*2d1d418eSSumit Saxena mpi3mr_update_device(sc, tgtdev, dev_pg0, false); 1949*2d1d418eSSumit Saxena if (!tgtdev->is_hidden && !tgtdev->exposed_to_os) 1950*2d1d418eSSumit Saxena mpi3mr_add_device(sc, perst_id); 1951*2d1d418eSSumit Saxena 1952*2d1d418eSSumit Saxena if (tgtdev->is_hidden && tgtdev->exposed_to_os) 1953*2d1d418eSSumit Saxena mpi3mr_remove_device_from_os(sc, tgtdev->dev_handle); 1954*2d1d418eSSumit Saxena } 1955*2d1d418eSSumit Saxena 1956*2d1d418eSSumit Saxena static void 1957*2d1d418eSSumit Saxena mpi3mr_fw_work(struct mpi3mr_softc *sc, struct mpi3mr_fw_event_work *fw_event) 1958*2d1d418eSSumit Saxena { 1959*2d1d418eSSumit Saxena if (sc->mpi3mr_flags & MPI3MR_FLAGS_SHUTDOWN) 1960*2d1d418eSSumit Saxena goto out; 1961*2d1d418eSSumit Saxena 1962*2d1d418eSSumit Saxena if (!fw_event->process_event) 1963*2d1d418eSSumit Saxena goto evt_ack; 1964*2d1d418eSSumit Saxena 1965*2d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_EVENT, "(%d)->(%s) Working on Event: [%x]\n", 1966*2d1d418eSSumit Saxena event_count++, __func__, fw_event->event); 1967*2d1d418eSSumit Saxena 1968*2d1d418eSSumit Saxena switch (fw_event->event) { 1969*2d1d418eSSumit Saxena case MPI3_EVENT_DEVICE_ADDED: 1970*2d1d418eSSumit Saxena { 1971*2d1d418eSSumit Saxena Mpi3DevicePage0_t *dev_pg0 = 1972*2d1d418eSSumit Saxena (Mpi3DevicePage0_t *) fw_event->event_data; 1973*2d1d418eSSumit Saxena mpi3mr_add_device(sc, dev_pg0->PersistentID); 1974*2d1d418eSSumit Saxena break; 1975*2d1d418eSSumit Saxena } 1976*2d1d418eSSumit Saxena case MPI3_EVENT_DEVICE_INFO_CHANGED: 1977*2d1d418eSSumit Saxena { 1978*2d1d418eSSumit Saxena mpi3mr_devinfochg_evt_bh(sc, 1979*2d1d418eSSumit Saxena (Mpi3DevicePage0_t *) fw_event->event_data); 1980*2d1d418eSSumit Saxena break; 1981*2d1d418eSSumit Saxena } 1982*2d1d418eSSumit Saxena case MPI3_EVENT_DEVICE_STATUS_CHANGE: 1983*2d1d418eSSumit Saxena { 1984*2d1d418eSSumit Saxena mpi3mr_devstatuschg_evt_bh(sc, fw_event); 1985*2d1d418eSSumit Saxena break; 1986*2d1d418eSSumit Saxena } 1987*2d1d418eSSumit Saxena case MPI3_EVENT_SAS_TOPOLOGY_CHANGE_LIST: 1988*2d1d418eSSumit Saxena { 1989*2d1d418eSSumit Saxena mpi3mr_process_sastopochg_evt(sc, fw_event); 1990*2d1d418eSSumit Saxena break; 1991*2d1d418eSSumit Saxena } 1992*2d1d418eSSumit Saxena case MPI3_EVENT_PCIE_TOPOLOGY_CHANGE_LIST: 1993*2d1d418eSSumit Saxena { 1994*2d1d418eSSumit Saxena mpi3mr_process_pcietopochg_evt(sc, fw_event); 1995*2d1d418eSSumit Saxena break; 1996*2d1d418eSSumit Saxena } 1997*2d1d418eSSumit Saxena case MPI3_EVENT_LOG_DATA: 1998*2d1d418eSSumit Saxena { 1999*2d1d418eSSumit Saxena mpi3mr_logdata_evt_bh(sc, fw_event); 2000*2d1d418eSSumit Saxena break; 2001*2d1d418eSSumit Saxena } 2002*2d1d418eSSumit Saxena default: 2003*2d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_TRACE,"Unhandled event 0x%0X\n", 2004*2d1d418eSSumit Saxena fw_event->event); 2005*2d1d418eSSumit Saxena break; 2006*2d1d418eSSumit Saxena 2007*2d1d418eSSumit Saxena } 2008*2d1d418eSSumit Saxena 2009*2d1d418eSSumit Saxena evt_ack: 2010*2d1d418eSSumit Saxena if (fw_event->send_ack) { 2011*2d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_EVENT,"Process event ACK for event 0x%0X\n", 2012*2d1d418eSSumit Saxena fw_event->event); 2013*2d1d418eSSumit Saxena mpi3mr_process_event_ack(sc, fw_event->event, 2014*2d1d418eSSumit Saxena fw_event->event_context); 2015*2d1d418eSSumit Saxena } 2016*2d1d418eSSumit Saxena 2017*2d1d418eSSumit Saxena out: 2018*2d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_EVENT, "(%d)->(%s) Event Free: [%x]\n", event_count, 2019*2d1d418eSSumit Saxena __func__, fw_event->event); 2020*2d1d418eSSumit Saxena 2021*2d1d418eSSumit Saxena mpi3mr_fw_event_free(sc, fw_event); 2022*2d1d418eSSumit Saxena } 2023*2d1d418eSSumit Saxena 2024*2d1d418eSSumit Saxena void 2025*2d1d418eSSumit Saxena mpi3mr_firmware_event_work(void *arg, int pending) 2026*2d1d418eSSumit Saxena { 2027*2d1d418eSSumit Saxena struct mpi3mr_fw_event_work *fw_event; 2028*2d1d418eSSumit Saxena struct mpi3mr_softc *sc; 2029*2d1d418eSSumit Saxena 2030*2d1d418eSSumit Saxena sc = (struct mpi3mr_softc *)arg; 2031*2d1d418eSSumit Saxena 2032*2d1d418eSSumit Saxena mtx_lock(&sc->fwevt_lock); 2033*2d1d418eSSumit Saxena while ((fw_event = TAILQ_FIRST(&sc->cam_sc->ev_queue)) != NULL) { 2034*2d1d418eSSumit Saxena TAILQ_REMOVE(&sc->cam_sc->ev_queue, fw_event, ev_link); 2035*2d1d418eSSumit Saxena mtx_unlock(&sc->fwevt_lock); 2036*2d1d418eSSumit Saxena mpi3mr_fw_work(sc, fw_event); 2037*2d1d418eSSumit Saxena mtx_lock(&sc->fwevt_lock); 2038*2d1d418eSSumit Saxena } 2039*2d1d418eSSumit Saxena mtx_unlock(&sc->fwevt_lock); 2040*2d1d418eSSumit Saxena } 2041*2d1d418eSSumit Saxena 2042*2d1d418eSSumit Saxena 2043*2d1d418eSSumit Saxena /* 2044*2d1d418eSSumit Saxena * mpi3mr_cam_attach - CAM layer registration 2045*2d1d418eSSumit Saxena * @sc: Adapter reference 2046*2d1d418eSSumit Saxena * 2047*2d1d418eSSumit Saxena * This function does simq allocation, cam registration, xpt_bus registration, 2048*2d1d418eSSumit Saxena * event taskqueue initialization and async event handler registration. 2049*2d1d418eSSumit Saxena * 2050*2d1d418eSSumit Saxena * Return: 0 on success and proper error codes on failure 2051*2d1d418eSSumit Saxena */ 2052*2d1d418eSSumit Saxena int 2053*2d1d418eSSumit Saxena mpi3mr_cam_attach(struct mpi3mr_softc *sc) 2054*2d1d418eSSumit Saxena { 2055*2d1d418eSSumit Saxena struct mpi3mr_cam_softc *cam_sc; 2056*2d1d418eSSumit Saxena cam_status status; 2057*2d1d418eSSumit Saxena int unit, error = 0, reqs; 2058*2d1d418eSSumit Saxena 2059*2d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_XINFO, "Starting CAM Attach\n"); 2060*2d1d418eSSumit Saxena 2061*2d1d418eSSumit Saxena cam_sc = malloc(sizeof(struct mpi3mr_cam_softc), M_MPI3MR, M_WAITOK|M_ZERO); 2062*2d1d418eSSumit Saxena if (!cam_sc) { 2063*2d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_ERROR, 2064*2d1d418eSSumit Saxena "Failed to allocate memory for controller CAM instance\n"); 2065*2d1d418eSSumit Saxena return (ENOMEM); 2066*2d1d418eSSumit Saxena } 2067*2d1d418eSSumit Saxena 2068*2d1d418eSSumit Saxena cam_sc->maxtargets = sc->facts.max_perids + 1; 2069*2d1d418eSSumit Saxena 2070*2d1d418eSSumit Saxena TAILQ_INIT(&cam_sc->tgt_list); 2071*2d1d418eSSumit Saxena 2072*2d1d418eSSumit Saxena sc->cam_sc = cam_sc; 2073*2d1d418eSSumit Saxena cam_sc->sc = sc; 2074*2d1d418eSSumit Saxena 2075*2d1d418eSSumit Saxena reqs = sc->max_host_ios; 2076*2d1d418eSSumit Saxena 2077*2d1d418eSSumit Saxena if ((cam_sc->devq = cam_simq_alloc(reqs)) == NULL) { 2078*2d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_ERROR, "Failed to allocate SIMQ\n"); 2079*2d1d418eSSumit Saxena error = ENOMEM; 2080*2d1d418eSSumit Saxena goto out; 2081*2d1d418eSSumit Saxena } 2082*2d1d418eSSumit Saxena 2083*2d1d418eSSumit Saxena unit = device_get_unit(sc->mpi3mr_dev); 2084*2d1d418eSSumit Saxena cam_sc->sim = cam_sim_alloc(mpi3mr_cam_action, mpi3mr_cam_poll, "mpi3mr", cam_sc, 2085*2d1d418eSSumit Saxena unit, &sc->mpi3mr_mtx, reqs, reqs, cam_sc->devq); 2086*2d1d418eSSumit Saxena if (cam_sc->sim == NULL) { 2087*2d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_ERROR, "Failed to allocate SIM\n"); 2088*2d1d418eSSumit Saxena error = EINVAL; 2089*2d1d418eSSumit Saxena goto out; 2090*2d1d418eSSumit Saxena } 2091*2d1d418eSSumit Saxena 2092*2d1d418eSSumit Saxena TAILQ_INIT(&cam_sc->ev_queue); 2093*2d1d418eSSumit Saxena 2094*2d1d418eSSumit Saxena /* Initialize taskqueue for Event Handling */ 2095*2d1d418eSSumit Saxena TASK_INIT(&cam_sc->ev_task, 0, mpi3mr_firmware_event_work, sc); 2096*2d1d418eSSumit Saxena cam_sc->ev_tq = taskqueue_create("mpi3mr_taskq", M_NOWAIT | M_ZERO, 2097*2d1d418eSSumit Saxena taskqueue_thread_enqueue, &cam_sc->ev_tq); 2098*2d1d418eSSumit Saxena taskqueue_start_threads(&cam_sc->ev_tq, 1, PRIBIO, "%s taskq", 2099*2d1d418eSSumit Saxena device_get_nameunit(sc->mpi3mr_dev)); 2100*2d1d418eSSumit Saxena 2101*2d1d418eSSumit Saxena mtx_lock(&sc->mpi3mr_mtx); 2102*2d1d418eSSumit Saxena 2103*2d1d418eSSumit Saxena /* 2104*2d1d418eSSumit Saxena * XXX There should be a bus for every port on the adapter, but since 2105*2d1d418eSSumit Saxena * we're just going to fake the topology for now, we'll pretend that 2106*2d1d418eSSumit Saxena * everything is just a target on a single bus. 2107*2d1d418eSSumit Saxena */ 2108*2d1d418eSSumit Saxena if ((error = xpt_bus_register(cam_sc->sim, sc->mpi3mr_dev, 0)) != 0) { 2109*2d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_ERROR, 2110*2d1d418eSSumit Saxena "Error 0x%x registering SCSI bus\n", error); 2111*2d1d418eSSumit Saxena mtx_unlock(&sc->mpi3mr_mtx); 2112*2d1d418eSSumit Saxena goto out; 2113*2d1d418eSSumit Saxena } 2114*2d1d418eSSumit Saxena 2115*2d1d418eSSumit Saxena /* 2116*2d1d418eSSumit Saxena * Assume that discovery events will start right away. 2117*2d1d418eSSumit Saxena * 2118*2d1d418eSSumit Saxena * Hold off boot until discovery is complete. 2119*2d1d418eSSumit Saxena */ 2120*2d1d418eSSumit Saxena cam_sc->flags |= MPI3MRSAS_IN_STARTUP | MPI3MRSAS_IN_DISCOVERY; 2121*2d1d418eSSumit Saxena sc->cam_sc->startup_refcount = 0; 2122*2d1d418eSSumit Saxena mpi3mr_startup_increment(cam_sc); 2123*2d1d418eSSumit Saxena 2124*2d1d418eSSumit Saxena callout_init(&cam_sc->discovery_callout, 1 /*mpsafe*/); 2125*2d1d418eSSumit Saxena 2126*2d1d418eSSumit Saxena /* 2127*2d1d418eSSumit Saxena * Register for async events so we can determine the EEDP 2128*2d1d418eSSumit Saxena * capabilities of devices. 2129*2d1d418eSSumit Saxena */ 2130*2d1d418eSSumit Saxena status = xpt_create_path(&cam_sc->path, /*periph*/NULL, 2131*2d1d418eSSumit Saxena cam_sim_path(sc->cam_sc->sim), CAM_TARGET_WILDCARD, 2132*2d1d418eSSumit Saxena CAM_LUN_WILDCARD); 2133*2d1d418eSSumit Saxena if (status != CAM_REQ_CMP) { 2134*2d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_ERROR, 2135*2d1d418eSSumit Saxena "Error 0x%x creating sim path\n", status); 2136*2d1d418eSSumit Saxena cam_sc->path = NULL; 2137*2d1d418eSSumit Saxena } 2138*2d1d418eSSumit Saxena 2139*2d1d418eSSumit Saxena if (status != CAM_REQ_CMP) { 2140*2d1d418eSSumit Saxena /* 2141*2d1d418eSSumit Saxena * EEDP use is the exception, not the rule. 2142*2d1d418eSSumit Saxena * Warn the user, but do not fail to attach. 2143*2d1d418eSSumit Saxena */ 2144*2d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_INFO, "EEDP capabilities disabled.\n"); 2145*2d1d418eSSumit Saxena } 2146*2d1d418eSSumit Saxena 2147*2d1d418eSSumit Saxena mtx_unlock(&sc->mpi3mr_mtx); 2148*2d1d418eSSumit Saxena 2149*2d1d418eSSumit Saxena error = mpi3mr_register_events(sc); 2150*2d1d418eSSumit Saxena 2151*2d1d418eSSumit Saxena out: 2152*2d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_XINFO, "%s Exiting CAM attach, error: 0x%x n", __func__, error); 2153*2d1d418eSSumit Saxena return (error); 2154*2d1d418eSSumit Saxena } 2155*2d1d418eSSumit Saxena 2156*2d1d418eSSumit Saxena int 2157*2d1d418eSSumit Saxena mpi3mr_cam_detach(struct mpi3mr_softc *sc) 2158*2d1d418eSSumit Saxena { 2159*2d1d418eSSumit Saxena struct mpi3mr_cam_softc *cam_sc; 2160*2d1d418eSSumit Saxena struct mpi3mr_target *target; 2161*2d1d418eSSumit Saxena 2162*2d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_XINFO, "%s, Starting CAM detach\n", __func__); 2163*2d1d418eSSumit Saxena if (sc->cam_sc == NULL) 2164*2d1d418eSSumit Saxena return (0); 2165*2d1d418eSSumit Saxena 2166*2d1d418eSSumit Saxena cam_sc = sc->cam_sc; 2167*2d1d418eSSumit Saxena 2168*2d1d418eSSumit Saxena mpi3mr_freeup_events(sc); 2169*2d1d418eSSumit Saxena 2170*2d1d418eSSumit Saxena /* 2171*2d1d418eSSumit Saxena * Drain and free the event handling taskqueue with the lock 2172*2d1d418eSSumit Saxena * unheld so that any parallel processing tasks drain properly 2173*2d1d418eSSumit Saxena * without deadlocking. 2174*2d1d418eSSumit Saxena */ 2175*2d1d418eSSumit Saxena if (cam_sc->ev_tq != NULL) 2176*2d1d418eSSumit Saxena taskqueue_free(cam_sc->ev_tq); 2177*2d1d418eSSumit Saxena 2178*2d1d418eSSumit Saxena mtx_lock(&sc->mpi3mr_mtx); 2179*2d1d418eSSumit Saxena 2180*2d1d418eSSumit Saxena while (cam_sc->startup_refcount != 0) 2181*2d1d418eSSumit Saxena mpi3mr_startup_decrement(cam_sc); 2182*2d1d418eSSumit Saxena 2183*2d1d418eSSumit Saxena /* Deregister our async handler */ 2184*2d1d418eSSumit Saxena if (cam_sc->path != NULL) { 2185*2d1d418eSSumit Saxena xpt_free_path(cam_sc->path); 2186*2d1d418eSSumit Saxena cam_sc->path = NULL; 2187*2d1d418eSSumit Saxena } 2188*2d1d418eSSumit Saxena 2189*2d1d418eSSumit Saxena if (cam_sc->flags & MPI3MRSAS_IN_STARTUP) 2190*2d1d418eSSumit Saxena xpt_release_simq(cam_sc->sim, 1); 2191*2d1d418eSSumit Saxena 2192*2d1d418eSSumit Saxena if (cam_sc->sim != NULL) { 2193*2d1d418eSSumit Saxena xpt_bus_deregister(cam_sim_path(cam_sc->sim)); 2194*2d1d418eSSumit Saxena cam_sim_free(cam_sc->sim, FALSE); 2195*2d1d418eSSumit Saxena } 2196*2d1d418eSSumit Saxena 2197*2d1d418eSSumit Saxena mtx_unlock(&sc->mpi3mr_mtx); 2198*2d1d418eSSumit Saxena 2199*2d1d418eSSumit Saxena if (cam_sc->devq != NULL) 2200*2d1d418eSSumit Saxena cam_simq_free(cam_sc->devq); 2201*2d1d418eSSumit Saxena 2202*2d1d418eSSumit Saxena get_target: 2203*2d1d418eSSumit Saxena mtx_lock_spin(&sc->target_lock); 2204*2d1d418eSSumit Saxena TAILQ_FOREACH(target, &cam_sc->tgt_list, tgt_next) { 2205*2d1d418eSSumit Saxena TAILQ_REMOVE(&sc->cam_sc->tgt_list, target, tgt_next); 2206*2d1d418eSSumit Saxena mtx_unlock_spin(&sc->target_lock); 2207*2d1d418eSSumit Saxena goto out_tgt_free; 2208*2d1d418eSSumit Saxena } 2209*2d1d418eSSumit Saxena mtx_unlock_spin(&sc->target_lock); 2210*2d1d418eSSumit Saxena out_tgt_free: 2211*2d1d418eSSumit Saxena if (target) { 2212*2d1d418eSSumit Saxena free(target, M_MPI3MR); 2213*2d1d418eSSumit Saxena target = NULL; 2214*2d1d418eSSumit Saxena goto get_target; 2215*2d1d418eSSumit Saxena } 2216*2d1d418eSSumit Saxena 2217*2d1d418eSSumit Saxena free(cam_sc, M_MPI3MR); 2218*2d1d418eSSumit Saxena sc->cam_sc = NULL; 2219*2d1d418eSSumit Saxena 2220*2d1d418eSSumit Saxena mpi3mr_dprint(sc, MPI3MR_XINFO, "%s, Exiting CAM detach\n", __func__); 2221*2d1d418eSSumit Saxena return (0); 2222*2d1d418eSSumit Saxena } 2223