1265236Sken/*- 2265236Sken * Copyright (c) 2009 Yahoo! Inc. 3283990Sslm * Copyright (c) 2011-2015 LSI Corp. 4299962Sslm * Copyright (c) 2013-2016 Avago Technologies 5265236Sken * All rights reserved. 6265236Sken * 7265236Sken * Redistribution and use in source and binary forms, with or without 8265236Sken * modification, are permitted provided that the following conditions 9265236Sken * are met: 10265236Sken * 1. Redistributions of source code must retain the above copyright 11265236Sken * notice, this list of conditions and the following disclaimer. 12265236Sken * 2. Redistributions in binary form must reproduce the above copyright 13265236Sken * notice, this list of conditions and the following disclaimer in the 14265236Sken * documentation and/or other materials provided with the distribution. 15265236Sken * 16265236Sken * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17265236Sken * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18265236Sken * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19265236Sken * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20265236Sken * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21265236Sken * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22265236Sken * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23265236Sken * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24265236Sken * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25265236Sken * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26265236Sken * SUCH DAMAGE. 27283990Sslm * 28283990Sslm * Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD 29283990Sslm * 30265236Sken */ 31265236Sken 32265236Sken#include <sys/cdefs.h> 33265236Sken__FBSDID("$FreeBSD: stable/10/sys/dev/mpr/mpr_sas.c 322661 2017-08-18 15:38:08Z ken $"); 34265236Sken 35283990Sslm/* Communications core for Avago Technologies (LSI) MPT3 */ 36265236Sken 37265236Sken/* TODO Move headers to mprvar */ 38265236Sken#include <sys/types.h> 39265236Sken#include <sys/param.h> 40265236Sken#include <sys/systm.h> 41265236Sken#include <sys/kernel.h> 42265236Sken#include <sys/selinfo.h> 43265236Sken#include <sys/module.h> 44265236Sken#include <sys/bus.h> 45265236Sken#include <sys/conf.h> 46265236Sken#include <sys/bio.h> 47265236Sken#include <sys/malloc.h> 48265236Sken#include <sys/uio.h> 49265236Sken#include <sys/sysctl.h> 50265236Sken#include <sys/endian.h> 51265236Sken#include <sys/queue.h> 52265236Sken#include <sys/kthread.h> 53265236Sken#include <sys/taskqueue.h> 54265236Sken#include <sys/sbuf.h> 55265236Sken 56265236Sken#include <machine/bus.h> 57265236Sken#include <machine/resource.h> 58265236Sken#include <sys/rman.h> 59265236Sken 60265236Sken#include <machine/stdarg.h> 61265236Sken 62265236Sken#include <cam/cam.h> 63265236Sken#include <cam/cam_ccb.h> 64265236Sken#include <cam/cam_debug.h> 65265236Sken#include <cam/cam_sim.h> 66265236Sken#include <cam/cam_xpt_sim.h> 67265236Sken#include <cam/cam_xpt_periph.h> 68265236Sken#include <cam/cam_periph.h> 69265236Sken#include <cam/scsi/scsi_all.h> 70265236Sken#include <cam/scsi/scsi_message.h> 71265236Sken#if __FreeBSD_version >= 900026 72265236Sken#include <cam/scsi/smp_all.h> 73265236Sken#endif 74265236Sken 75319436Sslm#include <dev/nvme/nvme.h> 76319436Sslm 77265236Sken#include <dev/mpr/mpi/mpi2_type.h> 78265236Sken#include <dev/mpr/mpi/mpi2.h> 79265236Sken#include <dev/mpr/mpi/mpi2_ioc.h> 80265236Sken#include <dev/mpr/mpi/mpi2_sas.h> 81319436Sslm#include <dev/mpr/mpi/mpi2_pci.h> 82265236Sken#include <dev/mpr/mpi/mpi2_cnfg.h> 83265236Sken#include <dev/mpr/mpi/mpi2_init.h> 84265236Sken#include <dev/mpr/mpi/mpi2_tool.h> 85265236Sken#include <dev/mpr/mpr_ioctl.h> 86265236Sken#include <dev/mpr/mprvar.h> 87265236Sken#include <dev/mpr/mpr_table.h> 88265236Sken#include <dev/mpr/mpr_sas.h> 89265236Sken 90265236Sken#define MPRSAS_DISCOVERY_TIMEOUT 20 91265236Sken#define MPRSAS_MAX_DISCOVERY_TIMEOUTS 10 /* 200 seconds */ 92265236Sken 93265236Sken/* 94265236Sken * static array to check SCSI OpCode for EEDP protection bits 95265236Sken */ 96265236Sken#define PRO_R MPI2_SCSIIO_EEDPFLAGS_CHECK_REMOVE_OP 97265236Sken#define PRO_W MPI2_SCSIIO_EEDPFLAGS_INSERT_OP 98265236Sken#define PRO_V MPI2_SCSIIO_EEDPFLAGS_INSERT_OP 99265236Skenstatic uint8_t op_code_prot[256] = { 100265236Sken 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 101265236Sken 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 102265236Sken 0, 0, 0, 0, 0, 0, 0, 0, PRO_R, 0, PRO_W, 0, 0, 0, PRO_W, PRO_V, 103265236Sken 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 104265236Sken 0, PRO_W, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 105265236Sken 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 106265236Sken 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 107265236Sken 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 108265236Sken 0, 0, 0, 0, 0, 0, 0, 0, PRO_R, 0, PRO_W, 0, 0, 0, PRO_W, PRO_V, 109265236Sken 0, 0, 0, PRO_W, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 110265236Sken 0, 0, 0, 0, 0, 0, 0, 0, PRO_R, 0, PRO_W, 0, 0, 0, PRO_W, PRO_V, 111265236Sken 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 112265236Sken 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 113265236Sken 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 114265236Sken 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 115265236Sken 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 116265236Sken}; 117265236Sken 118265236SkenMALLOC_DEFINE(M_MPRSAS, "MPRSAS", "MPR SAS memory"); 119265236Sken 120265236Skenstatic void mprsas_remove_device(struct mpr_softc *, struct mpr_command *); 121265236Skenstatic void mprsas_remove_complete(struct mpr_softc *, struct mpr_command *); 122265236Skenstatic void mprsas_action(struct cam_sim *sim, union ccb *ccb); 123265236Skenstatic void mprsas_poll(struct cam_sim *sim); 124265236Skenstatic void mprsas_scsiio_timeout(void *data); 125299962Sslmstatic void mprsas_abort_complete(struct mpr_softc *sc, struct mpr_command *cm); 126265236Skenstatic void mprsas_action_scsiio(struct mprsas_softc *, union ccb *); 127265236Skenstatic void mprsas_scsiio_complete(struct mpr_softc *, struct mpr_command *); 128265236Skenstatic void mprsas_action_resetdev(struct mprsas_softc *, union ccb *); 129299962Sslmstatic void mprsas_resetdev_complete(struct mpr_softc *, struct mpr_command *); 130283990Sslmstatic int mprsas_send_abort(struct mpr_softc *sc, struct mpr_command *tm, 131265236Sken struct mpr_command *cm); 132265236Skenstatic void mprsas_async(void *callback_arg, uint32_t code, 133265236Sken struct cam_path *path, void *arg); 134265236Sken#if (__FreeBSD_version < 901503) || \ 135265236Sken ((__FreeBSD_version >= 1000000) && (__FreeBSD_version < 1000006)) 136265236Skenstatic void mprsas_check_eedp(struct mpr_softc *sc, struct cam_path *path, 137265236Sken struct ccb_getdev *cgd); 138265236Skenstatic void mprsas_read_cap_done(struct cam_periph *periph, 139265236Sken union ccb *done_ccb); 140265236Sken#endif 141265236Skenstatic int mprsas_send_portenable(struct mpr_softc *sc); 142265236Skenstatic void mprsas_portenable_complete(struct mpr_softc *sc, 143265236Sken struct mpr_command *cm); 144265236Sken 145265236Sken#if __FreeBSD_version >= 900026 146299962Sslmstatic void mprsas_smpio_complete(struct mpr_softc *sc, struct mpr_command *cm); 147299962Sslmstatic void mprsas_send_smpcmd(struct mprsas_softc *sassc, union ccb *ccb, 148299962Sslm uint64_t sasaddr); 149283990Sslmstatic void mprsas_action_smpio(struct mprsas_softc *sassc, union ccb *ccb); 150283990Sslm#endif //FreeBSD_version >= 900026 151265236Sken 152265236Skenstruct mprsas_target * 153265236Skenmprsas_find_target_by_handle(struct mprsas_softc *sassc, int start, 154265236Sken uint16_t handle) 155265236Sken{ 156265236Sken struct mprsas_target *target; 157265236Sken int i; 158265236Sken 159265236Sken for (i = start; i < sassc->maxtargets; i++) { 160265236Sken target = &sassc->targets[i]; 161265236Sken if (target->handle == handle) 162265236Sken return (target); 163265236Sken } 164265236Sken 165265236Sken return (NULL); 166265236Sken} 167265236Sken 168265236Sken/* we need to freeze the simq during attach and diag reset, to avoid failing 169265236Sken * commands before device handles have been found by discovery. Since 170265236Sken * discovery involves reading config pages and possibly sending commands, 171265236Sken * discovery actions may continue even after we receive the end of discovery 172265236Sken * event, so refcount discovery actions instead of assuming we can unfreeze 173265236Sken * the simq when we get the event. 174265236Sken */ 175265236Skenvoid 176265236Skenmprsas_startup_increment(struct mprsas_softc *sassc) 177265236Sken{ 178265236Sken MPR_FUNCTRACE(sassc->sc); 179265236Sken 180265236Sken if ((sassc->flags & MPRSAS_IN_STARTUP) != 0) { 181265236Sken if (sassc->startup_refcount++ == 0) { 182265236Sken /* just starting, freeze the simq */ 183265236Sken mpr_dprint(sassc->sc, MPR_INIT, 184265236Sken "%s freezing simq\n", __func__); 185266548Sken#if (__FreeBSD_version >= 1000039) || \ 186266548Sken ((__FreeBSD_version < 1000000) && (__FreeBSD_version >= 902502)) 187265236Sken xpt_hold_boot(); 188265236Sken#endif 189265236Sken xpt_freeze_simq(sassc->sim, 1); 190265236Sken } 191265236Sken mpr_dprint(sassc->sc, MPR_INIT, "%s refcount %u\n", __func__, 192265236Sken sassc->startup_refcount); 193265236Sken } 194265236Sken} 195265236Sken 196265236Skenvoid 197265236Skenmprsas_release_simq_reinit(struct mprsas_softc *sassc) 198265236Sken{ 199265236Sken if (sassc->flags & MPRSAS_QUEUE_FROZEN) { 200265236Sken sassc->flags &= ~MPRSAS_QUEUE_FROZEN; 201265236Sken xpt_release_simq(sassc->sim, 1); 202265236Sken mpr_dprint(sassc->sc, MPR_INFO, "Unfreezing SIM queue\n"); 203265236Sken } 204265236Sken} 205265236Sken 206265236Skenvoid 207265236Skenmprsas_startup_decrement(struct mprsas_softc *sassc) 208265236Sken{ 209265236Sken MPR_FUNCTRACE(sassc->sc); 210265236Sken 211265236Sken if ((sassc->flags & MPRSAS_IN_STARTUP) != 0) { 212265236Sken if (--sassc->startup_refcount == 0) { 213265236Sken /* finished all discovery-related actions, release 214265236Sken * the simq and rescan for the latest topology. 215265236Sken */ 216265236Sken mpr_dprint(sassc->sc, MPR_INIT, 217265236Sken "%s releasing simq\n", __func__); 218265236Sken sassc->flags &= ~MPRSAS_IN_STARTUP; 219265236Sken xpt_release_simq(sassc->sim, 1); 220266548Sken#if (__FreeBSD_version >= 1000039) || \ 221266548Sken ((__FreeBSD_version < 1000000) && (__FreeBSD_version >= 902502)) 222265236Sken xpt_release_boot(); 223265236Sken#else 224265236Sken mprsas_rescan_target(sassc->sc, NULL); 225265236Sken#endif 226265236Sken } 227265236Sken mpr_dprint(sassc->sc, MPR_INIT, "%s refcount %u\n", __func__, 228265236Sken sassc->startup_refcount); 229265236Sken } 230265236Sken} 231265236Sken 232283990Sslm/* The firmware requires us to stop sending commands when we're doing task 233265236Sken * management, so refcount the TMs and keep the simq frozen when any are in 234265236Sken * use. 235265236Sken */ 236265236Skenstruct mpr_command * 237265236Skenmprsas_alloc_tm(struct mpr_softc *sc) 238265236Sken{ 239265236Sken struct mpr_command *tm; 240265236Sken 241265236Sken MPR_FUNCTRACE(sc); 242265236Sken tm = mpr_alloc_high_priority_command(sc); 243265236Sken return tm; 244265236Sken} 245265236Sken 246265236Skenvoid 247265236Skenmprsas_free_tm(struct mpr_softc *sc, struct mpr_command *tm) 248265236Sken{ 249299962Sslm int target_id = 0xFFFFFFFF; 250299962Sslm 251283990Sslm MPR_FUNCTRACE(sc); 252265236Sken if (tm == NULL) 253265236Sken return; 254265236Sken 255283990Sslm /* 256283990Sslm * For TM's the devq is frozen for the device. Unfreeze it here and 257283990Sslm * free the resources used for freezing the devq. Must clear the 258283990Sslm * INRESET flag as well or scsi I/O will not work. 259265236Sken */ 260283990Sslm if (tm->cm_targ != NULL) { 261283990Sslm tm->cm_targ->flags &= ~MPRSAS_TARGET_INRESET; 262299962Sslm target_id = tm->cm_targ->tid; 263265236Sken } 264283990Sslm if (tm->cm_ccb) { 265283990Sslm mpr_dprint(sc, MPR_INFO, "Unfreezing devq for target ID %d\n", 266299962Sslm target_id); 267283990Sslm xpt_release_devq(tm->cm_ccb->ccb_h.path, 1, TRUE); 268283990Sslm xpt_free_path(tm->cm_ccb->ccb_h.path); 269283990Sslm xpt_free_ccb(tm->cm_ccb); 270283990Sslm } 271265236Sken 272265236Sken mpr_free_high_priority_command(sc, tm); 273265236Sken} 274265236Sken 275265236Skenvoid 276265236Skenmprsas_rescan_target(struct mpr_softc *sc, struct mprsas_target *targ) 277265236Sken{ 278265236Sken struct mprsas_softc *sassc = sc->sassc; 279265236Sken path_id_t pathid; 280265236Sken target_id_t targetid; 281265236Sken union ccb *ccb; 282265236Sken 283265236Sken MPR_FUNCTRACE(sc); 284265236Sken pathid = cam_sim_path(sassc->sim); 285265236Sken if (targ == NULL) 286265236Sken targetid = CAM_TARGET_WILDCARD; 287265236Sken else 288265236Sken targetid = targ - sassc->targets; 289265236Sken 290265236Sken /* 291265236Sken * Allocate a CCB and schedule a rescan. 292265236Sken */ 293265236Sken ccb = xpt_alloc_ccb_nowait(); 294265236Sken if (ccb == NULL) { 295265236Sken mpr_dprint(sc, MPR_ERROR, "unable to alloc CCB for rescan\n"); 296265236Sken return; 297265236Sken } 298265236Sken 299283990Sslm if (xpt_create_path(&ccb->ccb_h.path, NULL, pathid, targetid, 300283990Sslm CAM_LUN_WILDCARD) != CAM_REQ_CMP) { 301265236Sken mpr_dprint(sc, MPR_ERROR, "unable to create path for rescan\n"); 302265236Sken xpt_free_ccb(ccb); 303265236Sken return; 304265236Sken } 305265236Sken 306265236Sken if (targetid == CAM_TARGET_WILDCARD) 307265236Sken ccb->ccb_h.func_code = XPT_SCAN_BUS; 308265236Sken else 309265236Sken ccb->ccb_h.func_code = XPT_SCAN_TGT; 310265236Sken 311265236Sken mpr_dprint(sc, MPR_TRACE, "%s targetid %u\n", __func__, targetid); 312265236Sken xpt_rescan(ccb); 313265236Sken} 314265236Sken 315265236Skenstatic void 316265236Skenmprsas_log_command(struct mpr_command *cm, u_int level, const char *fmt, ...) 317265236Sken{ 318265236Sken struct sbuf sb; 319265236Sken va_list ap; 320265236Sken char str[192]; 321265236Sken char path_str[64]; 322265236Sken 323265236Sken if (cm == NULL) 324265236Sken return; 325265236Sken 326265236Sken /* No need to be in here if debugging isn't enabled */ 327265236Sken if ((cm->cm_sc->mpr_debug & level) == 0) 328265236Sken return; 329265236Sken 330265236Sken sbuf_new(&sb, str, sizeof(str), 0); 331265236Sken 332265236Sken va_start(ap, fmt); 333265236Sken 334265236Sken if (cm->cm_ccb != NULL) { 335265236Sken xpt_path_string(cm->cm_ccb->csio.ccb_h.path, path_str, 336265236Sken sizeof(path_str)); 337265236Sken sbuf_cat(&sb, path_str); 338265236Sken if (cm->cm_ccb->ccb_h.func_code == XPT_SCSI_IO) { 339265236Sken scsi_command_string(&cm->cm_ccb->csio, &sb); 340265236Sken sbuf_printf(&sb, "length %d ", 341265236Sken cm->cm_ccb->csio.dxfer_len); 342265236Sken } 343265236Sken } else { 344265236Sken sbuf_printf(&sb, "(noperiph:%s%d:%u:%u:%u): ", 345265236Sken cam_sim_name(cm->cm_sc->sassc->sim), 346265236Sken cam_sim_unit(cm->cm_sc->sassc->sim), 347265236Sken cam_sim_bus(cm->cm_sc->sassc->sim), 348265236Sken cm->cm_targ ? cm->cm_targ->tid : 0xFFFFFFFF, 349265236Sken cm->cm_lun); 350265236Sken } 351265236Sken 352265236Sken sbuf_printf(&sb, "SMID %u ", cm->cm_desc.Default.SMID); 353265236Sken sbuf_vprintf(&sb, fmt, ap); 354265236Sken sbuf_finish(&sb); 355319436Sslm mpr_print_field(cm->cm_sc, "%s", sbuf_data(&sb)); 356265236Sken 357265236Sken va_end(ap); 358265236Sken} 359265236Sken 360265236Skenstatic void 361265236Skenmprsas_remove_volume(struct mpr_softc *sc, struct mpr_command *tm) 362265236Sken{ 363265236Sken MPI2_SCSI_TASK_MANAGE_REPLY *reply; 364265236Sken struct mprsas_target *targ; 365265236Sken uint16_t handle; 366265236Sken 367265236Sken MPR_FUNCTRACE(sc); 368265236Sken 369265236Sken reply = (MPI2_SCSI_TASK_MANAGE_REPLY *)tm->cm_reply; 370265236Sken handle = (uint16_t)(uintptr_t)tm->cm_complete_data; 371265236Sken targ = tm->cm_targ; 372265236Sken 373265236Sken if (reply == NULL) { 374265236Sken /* XXX retry the remove after the diag reset completes? */ 375265236Sken mpr_dprint(sc, MPR_FAULT, "%s NULL reply resetting device " 376265236Sken "0x%04x\n", __func__, handle); 377265236Sken mprsas_free_tm(sc, tm); 378265236Sken return; 379265236Sken } 380265236Sken 381299962Sslm if ((le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK) != 382299962Sslm MPI2_IOCSTATUS_SUCCESS) { 383299962Sslm mpr_dprint(sc, MPR_ERROR, "IOCStatus = 0x%x while resetting " 384299962Sslm "device 0x%x\n", le16toh(reply->IOCStatus), handle); 385265236Sken } 386265236Sken 387265236Sken mpr_dprint(sc, MPR_XINFO, "Reset aborted %u commands\n", 388299962Sslm le32toh(reply->TerminationCount)); 389265236Sken mpr_free_reply(sc, tm->cm_reply_data); 390265236Sken tm->cm_reply = NULL; /* Ensures the reply won't get re-freed */ 391265236Sken 392265236Sken mpr_dprint(sc, MPR_XINFO, "clearing target %u handle 0x%04x\n", 393265236Sken targ->tid, handle); 394265236Sken 395265236Sken /* 396265236Sken * Don't clear target if remove fails because things will get confusing. 397265236Sken * Leave the devname and sasaddr intact so that we know to avoid reusing 398265236Sken * this target id if possible, and so we can assign the same target id 399265236Sken * to this device if it comes back in the future. 400265236Sken */ 401299962Sslm if ((le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK) == 402299962Sslm MPI2_IOCSTATUS_SUCCESS) { 403265236Sken targ = tm->cm_targ; 404265236Sken targ->handle = 0x0; 405265236Sken targ->encl_handle = 0x0; 406265236Sken targ->encl_level_valid = 0x0; 407265236Sken targ->encl_level = 0x0; 408265236Sken targ->connector_name[0] = ' '; 409265236Sken targ->connector_name[1] = ' '; 410265236Sken targ->connector_name[2] = ' '; 411265236Sken targ->connector_name[3] = ' '; 412265236Sken targ->encl_slot = 0x0; 413265236Sken targ->exp_dev_handle = 0x0; 414265236Sken targ->phy_num = 0x0; 415265236Sken targ->linkrate = 0x0; 416265236Sken targ->devinfo = 0x0; 417265236Sken targ->flags = 0x0; 418265236Sken targ->scsi_req_desc_type = 0; 419265236Sken } 420265236Sken 421265236Sken mprsas_free_tm(sc, tm); 422265236Sken} 423265236Sken 424265236Sken 425265236Sken/* 426265236Sken * No Need to call "MPI2_SAS_OP_REMOVE_DEVICE" For Volume removal. 427265236Sken * Otherwise Volume Delete is same as Bare Drive Removal. 428265236Sken */ 429265236Skenvoid 430265236Skenmprsas_prepare_volume_remove(struct mprsas_softc *sassc, uint16_t handle) 431265236Sken{ 432265236Sken MPI2_SCSI_TASK_MANAGE_REQUEST *req; 433265236Sken struct mpr_softc *sc; 434265236Sken struct mpr_command *cm; 435265236Sken struct mprsas_target *targ = NULL; 436265236Sken 437265236Sken MPR_FUNCTRACE(sassc->sc); 438265236Sken sc = sassc->sc; 439265236Sken 440265236Sken targ = mprsas_find_target_by_handle(sassc, 0, handle); 441265236Sken if (targ == NULL) { 442265236Sken /* FIXME: what is the action? */ 443265236Sken /* We don't know about this device? */ 444265236Sken mpr_dprint(sc, MPR_ERROR, 445265236Sken "%s %d : invalid handle 0x%x \n", __func__,__LINE__, handle); 446265236Sken return; 447265236Sken } 448265236Sken 449265236Sken targ->flags |= MPRSAS_TARGET_INREMOVAL; 450265236Sken 451265236Sken cm = mprsas_alloc_tm(sc); 452265236Sken if (cm == NULL) { 453265236Sken mpr_dprint(sc, MPR_ERROR, 454265236Sken "%s: command alloc failure\n", __func__); 455265236Sken return; 456265236Sken } 457265236Sken 458265236Sken mprsas_rescan_target(sc, targ); 459265236Sken 460265236Sken req = (MPI2_SCSI_TASK_MANAGE_REQUEST *)cm->cm_req; 461265236Sken req->DevHandle = targ->handle; 462265236Sken req->Function = MPI2_FUNCTION_SCSI_TASK_MGMT; 463265236Sken req->TaskType = MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET; 464265236Sken 465265236Sken /* SAS Hard Link Reset / SATA Link Reset */ 466265236Sken req->MsgFlags = MPI2_SCSITASKMGMT_MSGFLAGS_LINK_RESET; 467265236Sken 468265236Sken cm->cm_targ = targ; 469265236Sken cm->cm_data = NULL; 470265236Sken cm->cm_desc.HighPriority.RequestFlags = 471265236Sken MPI2_REQ_DESCRIPT_FLAGS_HIGH_PRIORITY; 472265236Sken cm->cm_complete = mprsas_remove_volume; 473265236Sken cm->cm_complete_data = (void *)(uintptr_t)handle; 474283990Sslm 475283990Sslm mpr_dprint(sc, MPR_INFO, "%s: Sending reset for target ID %d\n", 476283990Sslm __func__, targ->tid); 477283990Sslm mprsas_prepare_for_tm(sc, cm, targ, CAM_LUN_WILDCARD); 478283990Sslm 479265236Sken mpr_map_command(sc, cm); 480265236Sken} 481265236Sken 482265236Sken/* 483319436Sslm * The firmware performs debounce on the link to avoid transient link errors 484319436Sslm * and false removals. When it does decide that link has been lost and a 485319436Sslm * device needs to go away, it expects that the host will perform a target reset 486319436Sslm * and then an op remove. The reset has the side-effect of aborting any 487319436Sslm * outstanding requests for the device, which is required for the op-remove to 488319436Sslm * succeed. It's not clear if the host should check for the device coming back 489319436Sslm * alive after the reset. 490265236Sken */ 491265236Skenvoid 492265236Skenmprsas_prepare_remove(struct mprsas_softc *sassc, uint16_t handle) 493265236Sken{ 494265236Sken MPI2_SCSI_TASK_MANAGE_REQUEST *req; 495265236Sken struct mpr_softc *sc; 496265236Sken struct mpr_command *cm; 497265236Sken struct mprsas_target *targ = NULL; 498265236Sken 499265236Sken MPR_FUNCTRACE(sassc->sc); 500265236Sken 501265236Sken sc = sassc->sc; 502265236Sken 503265236Sken targ = mprsas_find_target_by_handle(sassc, 0, handle); 504265236Sken if (targ == NULL) { 505265236Sken /* FIXME: what is the action? */ 506265236Sken /* We don't know about this device? */ 507265236Sken mpr_dprint(sc, MPR_ERROR, "%s : invalid handle 0x%x \n", 508265236Sken __func__, handle); 509265236Sken return; 510265236Sken } 511265236Sken 512265236Sken targ->flags |= MPRSAS_TARGET_INREMOVAL; 513265236Sken 514265236Sken cm = mprsas_alloc_tm(sc); 515265236Sken if (cm == NULL) { 516265236Sken mpr_dprint(sc, MPR_ERROR, "%s: command alloc failure\n", 517265236Sken __func__); 518265236Sken return; 519265236Sken } 520265236Sken 521265236Sken mprsas_rescan_target(sc, targ); 522265236Sken 523265236Sken req = (MPI2_SCSI_TASK_MANAGE_REQUEST *)cm->cm_req; 524265236Sken memset(req, 0, sizeof(*req)); 525265236Sken req->DevHandle = htole16(targ->handle); 526265236Sken req->Function = MPI2_FUNCTION_SCSI_TASK_MGMT; 527265236Sken req->TaskType = MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET; 528265236Sken 529265236Sken /* SAS Hard Link Reset / SATA Link Reset */ 530265236Sken req->MsgFlags = MPI2_SCSITASKMGMT_MSGFLAGS_LINK_RESET; 531265236Sken 532265236Sken cm->cm_targ = targ; 533265236Sken cm->cm_data = NULL; 534265236Sken cm->cm_desc.HighPriority.RequestFlags = 535265236Sken MPI2_REQ_DESCRIPT_FLAGS_HIGH_PRIORITY; 536265236Sken cm->cm_complete = mprsas_remove_device; 537265236Sken cm->cm_complete_data = (void *)(uintptr_t)handle; 538283990Sslm 539283990Sslm mpr_dprint(sc, MPR_INFO, "%s: Sending reset for target ID %d\n", 540283990Sslm __func__, targ->tid); 541283990Sslm mprsas_prepare_for_tm(sc, cm, targ, CAM_LUN_WILDCARD); 542283990Sslm 543265236Sken mpr_map_command(sc, cm); 544265236Sken} 545265236Sken 546265236Skenstatic void 547265236Skenmprsas_remove_device(struct mpr_softc *sc, struct mpr_command *tm) 548265236Sken{ 549265236Sken MPI2_SCSI_TASK_MANAGE_REPLY *reply; 550265236Sken MPI2_SAS_IOUNIT_CONTROL_REQUEST *req; 551265236Sken struct mprsas_target *targ; 552265236Sken struct mpr_command *next_cm; 553265236Sken uint16_t handle; 554265236Sken 555265236Sken MPR_FUNCTRACE(sc); 556265236Sken 557265236Sken reply = (MPI2_SCSI_TASK_MANAGE_REPLY *)tm->cm_reply; 558265236Sken handle = (uint16_t)(uintptr_t)tm->cm_complete_data; 559265236Sken targ = tm->cm_targ; 560265236Sken 561265236Sken /* 562265236Sken * Currently there should be no way we can hit this case. It only 563265236Sken * happens when we have a failure to allocate chain frames, and 564265236Sken * task management commands don't have S/G lists. 565265236Sken */ 566265236Sken if ((tm->cm_flags & MPR_CM_FLAGS_ERROR_MASK) != 0) { 567265236Sken mpr_dprint(sc, MPR_ERROR, "%s: cm_flags = %#x for remove of " 568265236Sken "handle %#04x! This should not happen!\n", __func__, 569265236Sken tm->cm_flags, handle); 570265236Sken } 571265236Sken 572265236Sken if (reply == NULL) { 573265236Sken /* XXX retry the remove after the diag reset completes? */ 574265236Sken mpr_dprint(sc, MPR_FAULT, "%s NULL reply resetting device " 575265236Sken "0x%04x\n", __func__, handle); 576265236Sken mprsas_free_tm(sc, tm); 577265236Sken return; 578265236Sken } 579265236Sken 580299962Sslm if ((le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK) != 581299962Sslm MPI2_IOCSTATUS_SUCCESS) { 582299962Sslm mpr_dprint(sc, MPR_ERROR, "IOCStatus = 0x%x while resetting " 583265236Sken "device 0x%x\n", le16toh(reply->IOCStatus), handle); 584265236Sken } 585265236Sken 586265236Sken mpr_dprint(sc, MPR_XINFO, "Reset aborted %u commands\n", 587265236Sken le32toh(reply->TerminationCount)); 588265236Sken mpr_free_reply(sc, tm->cm_reply_data); 589265236Sken tm->cm_reply = NULL; /* Ensures the reply won't get re-freed */ 590265236Sken 591265236Sken /* Reuse the existing command */ 592265236Sken req = (MPI2_SAS_IOUNIT_CONTROL_REQUEST *)tm->cm_req; 593265236Sken memset(req, 0, sizeof(*req)); 594265236Sken req->Function = MPI2_FUNCTION_SAS_IO_UNIT_CONTROL; 595265236Sken req->Operation = MPI2_SAS_OP_REMOVE_DEVICE; 596265236Sken req->DevHandle = htole16(handle); 597265236Sken tm->cm_data = NULL; 598265236Sken tm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 599265236Sken tm->cm_complete = mprsas_remove_complete; 600265236Sken tm->cm_complete_data = (void *)(uintptr_t)handle; 601265236Sken 602265236Sken mpr_map_command(sc, tm); 603265236Sken 604283990Sslm mpr_dprint(sc, MPR_INFO, "clearing target %u handle 0x%04x\n", 605265236Sken targ->tid, handle); 606265236Sken if (targ->encl_level_valid) { 607283990Sslm mpr_dprint(sc, MPR_INFO, "At enclosure level %d, slot %d, " 608265236Sken "connector name (%4s)\n", targ->encl_level, targ->encl_slot, 609265236Sken targ->connector_name); 610265236Sken } 611265236Sken TAILQ_FOREACH_SAFE(tm, &targ->commands, cm_link, next_cm) { 612265236Sken union ccb *ccb; 613265236Sken 614265236Sken mpr_dprint(sc, MPR_XINFO, "Completing missed command %p\n", tm); 615265236Sken ccb = tm->cm_complete_data; 616283990Sslm mprsas_set_ccbstatus(ccb, CAM_DEV_NOT_THERE); 617265236Sken mprsas_scsiio_complete(sc, tm); 618265236Sken } 619265236Sken} 620265236Sken 621265236Skenstatic void 622265236Skenmprsas_remove_complete(struct mpr_softc *sc, struct mpr_command *tm) 623265236Sken{ 624265236Sken MPI2_SAS_IOUNIT_CONTROL_REPLY *reply; 625265236Sken uint16_t handle; 626265236Sken struct mprsas_target *targ; 627265236Sken struct mprsas_lun *lun; 628265236Sken 629265236Sken MPR_FUNCTRACE(sc); 630265236Sken 631265236Sken reply = (MPI2_SAS_IOUNIT_CONTROL_REPLY *)tm->cm_reply; 632265236Sken handle = (uint16_t)(uintptr_t)tm->cm_complete_data; 633265236Sken 634265236Sken /* 635265236Sken * Currently there should be no way we can hit this case. It only 636265236Sken * happens when we have a failure to allocate chain frames, and 637265236Sken * task management commands don't have S/G lists. 638265236Sken */ 639265236Sken if ((tm->cm_flags & MPR_CM_FLAGS_ERROR_MASK) != 0) { 640265236Sken mpr_dprint(sc, MPR_XINFO, "%s: cm_flags = %#x for remove of " 641265236Sken "handle %#04x! This should not happen!\n", __func__, 642265236Sken tm->cm_flags, handle); 643265236Sken mprsas_free_tm(sc, tm); 644265236Sken return; 645265236Sken } 646265236Sken 647265236Sken if (reply == NULL) { 648265236Sken /* most likely a chip reset */ 649265236Sken mpr_dprint(sc, MPR_FAULT, "%s NULL reply removing device " 650265236Sken "0x%04x\n", __func__, handle); 651265236Sken mprsas_free_tm(sc, tm); 652265236Sken return; 653265236Sken } 654265236Sken 655265236Sken mpr_dprint(sc, MPR_XINFO, "%s on handle 0x%04x, IOCStatus= 0x%x\n", 656265236Sken __func__, handle, le16toh(reply->IOCStatus)); 657265236Sken 658265236Sken /* 659265236Sken * Don't clear target if remove fails because things will get confusing. 660265236Sken * Leave the devname and sasaddr intact so that we know to avoid reusing 661265236Sken * this target id if possible, and so we can assign the same target id 662265236Sken * to this device if it comes back in the future. 663265236Sken */ 664299962Sslm if ((le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK) == 665299962Sslm MPI2_IOCSTATUS_SUCCESS) { 666265236Sken targ = tm->cm_targ; 667265236Sken targ->handle = 0x0; 668265236Sken targ->encl_handle = 0x0; 669265236Sken targ->encl_level_valid = 0x0; 670265236Sken targ->encl_level = 0x0; 671265236Sken targ->connector_name[0] = ' '; 672265236Sken targ->connector_name[1] = ' '; 673265236Sken targ->connector_name[2] = ' '; 674265236Sken targ->connector_name[3] = ' '; 675265236Sken targ->encl_slot = 0x0; 676265236Sken targ->exp_dev_handle = 0x0; 677265236Sken targ->phy_num = 0x0; 678265236Sken targ->linkrate = 0x0; 679265236Sken targ->devinfo = 0x0; 680265236Sken targ->flags = 0x0; 681265236Sken targ->scsi_req_desc_type = 0; 682265236Sken 683265236Sken while (!SLIST_EMPTY(&targ->luns)) { 684265236Sken lun = SLIST_FIRST(&targ->luns); 685265236Sken SLIST_REMOVE_HEAD(&targ->luns, lun_link); 686265236Sken free(lun, M_MPR); 687265236Sken } 688265236Sken } 689265236Sken 690265236Sken mprsas_free_tm(sc, tm); 691265236Sken} 692265236Sken 693265236Skenstatic int 694265236Skenmprsas_register_events(struct mpr_softc *sc) 695265236Sken{ 696265236Sken uint8_t events[16]; 697265236Sken 698265236Sken bzero(events, 16); 699265236Sken setbit(events, MPI2_EVENT_SAS_DEVICE_STATUS_CHANGE); 700265236Sken setbit(events, MPI2_EVENT_SAS_DISCOVERY); 701265236Sken setbit(events, MPI2_EVENT_SAS_BROADCAST_PRIMITIVE); 702265236Sken setbit(events, MPI2_EVENT_SAS_INIT_DEVICE_STATUS_CHANGE); 703265236Sken setbit(events, MPI2_EVENT_SAS_INIT_TABLE_OVERFLOW); 704265236Sken setbit(events, MPI2_EVENT_SAS_TOPOLOGY_CHANGE_LIST); 705265236Sken setbit(events, MPI2_EVENT_SAS_ENCL_DEVICE_STATUS_CHANGE); 706265236Sken setbit(events, MPI2_EVENT_IR_CONFIGURATION_CHANGE_LIST); 707265236Sken setbit(events, MPI2_EVENT_IR_VOLUME); 708265236Sken setbit(events, MPI2_EVENT_IR_PHYSICAL_DISK); 709265236Sken setbit(events, MPI2_EVENT_IR_OPERATION_STATUS); 710265236Sken setbit(events, MPI2_EVENT_TEMP_THRESHOLD); 711319436Sslm if (sc->facts->MsgVersion >= MPI2_VERSION_02_06) { 712319436Sslm setbit(events, MPI2_EVENT_ACTIVE_CABLE_EXCEPTION); 713319436Sslm if (sc->mpr_flags & MPR_FLAGS_GEN35_IOC) { 714319436Sslm setbit(events, MPI2_EVENT_PCIE_DEVICE_STATUS_CHANGE); 715319436Sslm setbit(events, MPI2_EVENT_PCIE_ENUMERATION); 716319436Sslm setbit(events, MPI2_EVENT_PCIE_TOPOLOGY_CHANGE_LIST); 717319436Sslm } 718319436Sslm } 719265236Sken 720265236Sken mpr_register_events(sc, events, mprsas_evt_handler, NULL, 721265236Sken &sc->sassc->mprsas_eh); 722265236Sken 723265236Sken return (0); 724265236Sken} 725265236Sken 726265236Skenint 727265236Skenmpr_attach_sas(struct mpr_softc *sc) 728265236Sken{ 729265236Sken struct mprsas_softc *sassc; 730265236Sken cam_status status; 731265236Sken int unit, error = 0; 732265236Sken 733265236Sken MPR_FUNCTRACE(sc); 734265236Sken 735265236Sken sassc = malloc(sizeof(struct mprsas_softc), M_MPR, M_WAITOK|M_ZERO); 736265236Sken if (!sassc) { 737265236Sken device_printf(sc->mpr_dev, "Cannot allocate memory %s %d\n", 738265236Sken __func__, __LINE__); 739265236Sken return (ENOMEM); 740265236Sken } 741265236Sken 742265236Sken /* 743283990Sslm * XXX MaxTargets could change during a reinit. Since we don't 744265236Sken * resize the targets[] array during such an event, cache the value 745265236Sken * of MaxTargets here so that we don't get into trouble later. This 746265236Sken * should move into the reinit logic. 747265236Sken */ 748319445Sslm sassc->maxtargets = sc->facts->MaxTargets + sc->facts->MaxVolumes; 749265236Sken sassc->targets = malloc(sizeof(struct mprsas_target) * 750265236Sken sassc->maxtargets, M_MPR, M_WAITOK|M_ZERO); 751265236Sken if (!sassc->targets) { 752265236Sken device_printf(sc->mpr_dev, "Cannot allocate memory %s %d\n", 753265236Sken __func__, __LINE__); 754265236Sken free(sassc, M_MPR); 755265236Sken return (ENOMEM); 756265236Sken } 757265236Sken sc->sassc = sassc; 758265236Sken sassc->sc = sc; 759265236Sken 760265236Sken if ((sassc->devq = cam_simq_alloc(sc->num_reqs)) == NULL) { 761265236Sken mpr_dprint(sc, MPR_ERROR, "Cannot allocate SIMQ\n"); 762265236Sken error = ENOMEM; 763265236Sken goto out; 764265236Sken } 765265236Sken 766265236Sken unit = device_get_unit(sc->mpr_dev); 767265236Sken sassc->sim = cam_sim_alloc(mprsas_action, mprsas_poll, "mpr", sassc, 768265236Sken unit, &sc->mpr_mtx, sc->num_reqs, sc->num_reqs, sassc->devq); 769265236Sken if (sassc->sim == NULL) { 770265236Sken mpr_dprint(sc, MPR_ERROR, "Cannot allocate SIM\n"); 771265236Sken error = EINVAL; 772265236Sken goto out; 773265236Sken } 774265236Sken 775265236Sken TAILQ_INIT(&sassc->ev_queue); 776265236Sken 777265236Sken /* Initialize taskqueue for Event Handling */ 778265236Sken TASK_INIT(&sassc->ev_task, 0, mprsas_firmware_event_work, sc); 779265236Sken sassc->ev_tq = taskqueue_create("mpr_taskq", M_NOWAIT | M_ZERO, 780265236Sken taskqueue_thread_enqueue, &sassc->ev_tq); 781297700Smav taskqueue_start_threads(&sassc->ev_tq, 1, PRIBIO, "%s taskq", 782265236Sken device_get_nameunit(sc->mpr_dev)); 783265236Sken 784265236Sken mpr_lock(sc); 785265236Sken 786265236Sken /* 787265236Sken * XXX There should be a bus for every port on the adapter, but since 788265236Sken * we're just going to fake the topology for now, we'll pretend that 789265236Sken * everything is just a target on a single bus. 790265236Sken */ 791265236Sken if ((error = xpt_bus_register(sassc->sim, sc->mpr_dev, 0)) != 0) { 792265236Sken mpr_dprint(sc, MPR_ERROR, "Error %d registering SCSI bus\n", 793265236Sken error); 794265236Sken mpr_unlock(sc); 795265236Sken goto out; 796265236Sken } 797265236Sken 798265236Sken /* 799283990Sslm * Assume that discovery events will start right away. 800265236Sken * 801265236Sken * Hold off boot until discovery is complete. 802265236Sken */ 803265236Sken sassc->flags |= MPRSAS_IN_STARTUP | MPRSAS_IN_DISCOVERY; 804265236Sken sc->sassc->startup_refcount = 0; 805265236Sken mprsas_startup_increment(sassc); 806265236Sken 807283990Sslm callout_init(&sassc->discovery_callout, 1 /*mpsafe*/); 808265236Sken 809265236Sken /* 810265236Sken * Register for async events so we can determine the EEDP 811265236Sken * capabilities of devices. 812265236Sken */ 813265236Sken status = xpt_create_path(&sassc->path, /*periph*/NULL, 814265236Sken cam_sim_path(sc->sassc->sim), CAM_TARGET_WILDCARD, 815265236Sken CAM_LUN_WILDCARD); 816265236Sken if (status != CAM_REQ_CMP) { 817265236Sken mpr_printf(sc, "Error %#x creating sim path\n", status); 818265236Sken sassc->path = NULL; 819265236Sken } else { 820265236Sken int event; 821265236Sken 822265236Sken#if (__FreeBSD_version >= 1000006) || \ 823265236Sken ((__FreeBSD_version >= 901503) && (__FreeBSD_version < 1000000)) 824265236Sken event = AC_ADVINFO_CHANGED | AC_FOUND_DEVICE; 825265236Sken#else 826265236Sken event = AC_FOUND_DEVICE; 827265236Sken#endif 828265730Sken 829265730Sken /* 830265730Sken * Prior to the CAM locking improvements, we can't call 831265730Sken * xpt_register_async() with a particular path specified. 832265730Sken * 833265730Sken * If a path isn't specified, xpt_register_async() will 834265730Sken * generate a wildcard path and acquire the XPT lock while 835265730Sken * it calls xpt_action() to execute the XPT_SASYNC_CB CCB. 836265730Sken * It will then drop the XPT lock once that is done. 837265730Sken * 838265730Sken * If a path is specified for xpt_register_async(), it will 839265730Sken * not acquire and drop the XPT lock around the call to 840265730Sken * xpt_action(). xpt_action() asserts that the caller 841265730Sken * holds the SIM lock, so the SIM lock has to be held when 842265730Sken * calling xpt_register_async() when the path is specified. 843265730Sken * 844265730Sken * But xpt_register_async calls xpt_for_all_devices(), 845265730Sken * which calls xptbustraverse(), which will acquire each 846265730Sken * SIM lock. When it traverses our particular bus, it will 847265730Sken * necessarily acquire the SIM lock, which will lead to a 848265730Sken * recursive lock acquisition. 849265730Sken * 850265730Sken * The CAM locking changes fix this problem by acquiring 851265730Sken * the XPT topology lock around bus traversal in 852265730Sken * xptbustraverse(), so the caller can hold the SIM lock 853265730Sken * and it does not cause a recursive lock acquisition. 854265730Sken * 855265730Sken * These __FreeBSD_version values are approximate, especially 856265730Sken * for stable/10, which is two months later than the actual 857265730Sken * change. 858265730Sken */ 859265730Sken 860265730Sken#if (__FreeBSD_version < 1000703) || \ 861265730Sken ((__FreeBSD_version >= 1100000) && (__FreeBSD_version < 1100002)) 862265730Sken mpr_unlock(sc); 863265236Sken status = xpt_register_async(event, mprsas_async, sc, 864265730Sken NULL); 865265730Sken mpr_lock(sc); 866265730Sken#else 867265730Sken status = xpt_register_async(event, mprsas_async, sc, 868265236Sken sassc->path); 869265730Sken#endif 870265730Sken 871265236Sken if (status != CAM_REQ_CMP) { 872265236Sken mpr_dprint(sc, MPR_ERROR, 873265236Sken "Error %#x registering async handler for " 874265236Sken "AC_ADVINFO_CHANGED events\n", status); 875265236Sken xpt_free_path(sassc->path); 876265236Sken sassc->path = NULL; 877265236Sken } 878265236Sken } 879265236Sken if (status != CAM_REQ_CMP) { 880265236Sken /* 881265236Sken * EEDP use is the exception, not the rule. 882265236Sken * Warn the user, but do not fail to attach. 883265236Sken */ 884265236Sken mpr_printf(sc, "EEDP capabilities disabled.\n"); 885265236Sken } 886265236Sken 887265236Sken mpr_unlock(sc); 888265236Sken 889265236Sken mprsas_register_events(sc); 890265236Skenout: 891265236Sken if (error) 892265236Sken mpr_detach_sas(sc); 893265236Sken return (error); 894265236Sken} 895265236Sken 896265236Skenint 897265236Skenmpr_detach_sas(struct mpr_softc *sc) 898265236Sken{ 899265236Sken struct mprsas_softc *sassc; 900265236Sken struct mprsas_lun *lun, *lun_tmp; 901265236Sken struct mprsas_target *targ; 902265236Sken int i; 903265236Sken 904265236Sken MPR_FUNCTRACE(sc); 905265236Sken 906265236Sken if (sc->sassc == NULL) 907265236Sken return (0); 908265236Sken 909265236Sken sassc = sc->sassc; 910265236Sken mpr_deregister_events(sc, sassc->mprsas_eh); 911265236Sken 912265236Sken /* 913265236Sken * Drain and free the event handling taskqueue with the lock 914265236Sken * unheld so that any parallel processing tasks drain properly 915265236Sken * without deadlocking. 916265236Sken */ 917265236Sken if (sassc->ev_tq != NULL) 918265236Sken taskqueue_free(sassc->ev_tq); 919265236Sken 920265236Sken /* Make sure CAM doesn't wedge if we had to bail out early. */ 921265236Sken mpr_lock(sc); 922265236Sken 923265236Sken /* Deregister our async handler */ 924265236Sken if (sassc->path != NULL) { 925265236Sken xpt_register_async(0, mprsas_async, sc, sassc->path); 926265236Sken xpt_free_path(sassc->path); 927265236Sken sassc->path = NULL; 928265236Sken } 929265236Sken 930265236Sken if (sassc->flags & MPRSAS_IN_STARTUP) 931265236Sken xpt_release_simq(sassc->sim, 1); 932265236Sken 933265236Sken if (sassc->sim != NULL) { 934265236Sken xpt_bus_deregister(cam_sim_path(sassc->sim)); 935265236Sken cam_sim_free(sassc->sim, FALSE); 936265236Sken } 937265236Sken 938265236Sken mpr_unlock(sc); 939265236Sken 940265236Sken if (sassc->devq != NULL) 941265236Sken cam_simq_free(sassc->devq); 942265236Sken 943265236Sken for (i = 0; i < sassc->maxtargets; i++) { 944265236Sken targ = &sassc->targets[i]; 945265236Sken SLIST_FOREACH_SAFE(lun, &targ->luns, lun_link, lun_tmp) { 946265236Sken free(lun, M_MPR); 947265236Sken } 948265236Sken } 949265236Sken free(sassc->targets, M_MPR); 950265236Sken free(sassc, M_MPR); 951265236Sken sc->sassc = NULL; 952265236Sken 953265236Sken return (0); 954265236Sken} 955265236Sken 956265236Skenvoid 957265236Skenmprsas_discovery_end(struct mprsas_softc *sassc) 958265236Sken{ 959265236Sken struct mpr_softc *sc = sassc->sc; 960265236Sken 961265236Sken MPR_FUNCTRACE(sc); 962265236Sken 963265236Sken if (sassc->flags & MPRSAS_DISCOVERY_TIMEOUT_PENDING) 964265236Sken callout_stop(&sassc->discovery_callout); 965265236Sken 966319445Sslm /* 967319445Sslm * After discovery has completed, check the mapping table for any 968319445Sslm * missing devices and update their missing counts. Only do this once 969319445Sslm * whenever the driver is initialized so that missing counts aren't 970319445Sslm * updated unnecessarily. Note that just because discovery has 971319445Sslm * completed doesn't mean that events have been processed yet. The 972319445Sslm * check_devices function is a callout timer that checks if ALL devices 973319445Sslm * are missing. If so, it will wait a little longer for events to 974319445Sslm * complete and keep resetting itself until some device in the mapping 975319445Sslm * table is not missing, meaning that event processing has started. 976319445Sslm */ 977319445Sslm if (sc->track_mapping_events) { 978319445Sslm mpr_dprint(sc, MPR_XINFO | MPR_MAPPING, "Discovery has " 979319445Sslm "completed. Check for missing devices in the mapping " 980319445Sslm "table.\n"); 981319445Sslm callout_reset(&sc->device_check_callout, 982319445Sslm MPR_MISSING_CHECK_DELAY * hz, mpr_mapping_check_devices, 983319445Sslm sc); 984319445Sslm } 985265236Sken} 986265236Sken 987265236Skenstatic void 988265236Skenmprsas_action(struct cam_sim *sim, union ccb *ccb) 989265236Sken{ 990265236Sken struct mprsas_softc *sassc; 991265236Sken 992265236Sken sassc = cam_sim_softc(sim); 993265236Sken 994265236Sken MPR_FUNCTRACE(sassc->sc); 995283990Sslm mpr_dprint(sassc->sc, MPR_TRACE, "ccb func_code 0x%x\n", 996265236Sken ccb->ccb_h.func_code); 997265236Sken mtx_assert(&sassc->sc->mpr_mtx, MA_OWNED); 998265236Sken 999265236Sken switch (ccb->ccb_h.func_code) { 1000265236Sken case XPT_PATH_INQ: 1001265236Sken { 1002265236Sken struct ccb_pathinq *cpi = &ccb->cpi; 1003303089Sslm struct mpr_softc *sc = sassc->sc; 1004303089Sslm uint8_t sges_per_frame; 1005265236Sken 1006265236Sken cpi->version_num = 1; 1007265236Sken cpi->hba_inquiry = PI_SDTR_ABLE|PI_TAG_ABLE|PI_WIDE_16; 1008265236Sken cpi->target_sprt = 0; 1009266548Sken#if (__FreeBSD_version >= 1000039) || \ 1010266548Sken ((__FreeBSD_version < 1000000) && (__FreeBSD_version >= 902502)) 1011265236Sken cpi->hba_misc = PIM_NOBUSRESET | PIM_UNMAPPED | PIM_NOSCAN; 1012265236Sken#else 1013265236Sken cpi->hba_misc = PIM_NOBUSRESET | PIM_UNMAPPED; 1014265236Sken#endif 1015265236Sken cpi->hba_eng_cnt = 0; 1016265236Sken cpi->max_target = sassc->maxtargets - 1; 1017265236Sken cpi->max_lun = 255; 1018319445Sslm 1019319445Sslm /* 1020319445Sslm * initiator_id is set here to an ID outside the set of valid 1021319445Sslm * target IDs (including volumes). 1022319445Sslm */ 1023319445Sslm cpi->initiator_id = sassc->maxtargets; 1024315813Smav strlcpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN); 1025315813Smav strlcpy(cpi->hba_vid, "Avago Tech", HBA_IDLEN); 1026315813Smav strlcpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN); 1027265236Sken cpi->unit_number = cam_sim_unit(sim); 1028265236Sken cpi->bus_id = cam_sim_bus(sim); 1029265236Sken /* 1030265236Sken * XXXSLM-I think this needs to change based on config page or 1031265236Sken * something instead of hardcoded to 150000. 1032265236Sken */ 1033265236Sken cpi->base_transfer_speed = 150000; 1034265236Sken cpi->transport = XPORT_SAS; 1035265236Sken cpi->transport_version = 0; 1036265236Sken cpi->protocol = PROTO_SCSI; 1037265236Sken cpi->protocol_version = SCSI_REV_SPC; 1038303089Sslm 1039265236Sken /* 1040303089Sslm * Max IO Size is Page Size * the following: 1041303089Sslm * ((SGEs per frame - 1 for chain element) * 1042303089Sslm * Max Chain Depth) + 1 for no chain needed in last frame 1043303089Sslm * 1044303089Sslm * If user suggests a Max IO size to use, use the smaller of the 1045303089Sslm * user's value and the calculated value as long as the user's 1046303089Sslm * value is larger than 0. The user's value is in pages. 1047265236Sken */ 1048303089Sslm sges_per_frame = (sc->chain_frame_size / 1049303089Sslm sizeof(MPI2_IEEE_SGE_SIMPLE64)) - 1; 1050303089Sslm cpi->maxio = (sges_per_frame * sc->facts->MaxChainDepth) + 1; 1051303089Sslm cpi->maxio *= PAGE_SIZE; 1052303089Sslm if ((sc->max_io_pages > 0) && (sc->max_io_pages * PAGE_SIZE < 1053303089Sslm cpi->maxio)) 1054303089Sslm cpi->maxio = sc->max_io_pages * PAGE_SIZE; 1055319436Sslm sc->maxio = cpi->maxio; 1056283990Sslm mprsas_set_ccbstatus(ccb, CAM_REQ_CMP); 1057265236Sken break; 1058265236Sken } 1059265236Sken case XPT_GET_TRAN_SETTINGS: 1060265236Sken { 1061265236Sken struct ccb_trans_settings *cts; 1062265236Sken struct ccb_trans_settings_sas *sas; 1063265236Sken struct ccb_trans_settings_scsi *scsi; 1064265236Sken struct mprsas_target *targ; 1065265236Sken 1066265236Sken cts = &ccb->cts; 1067265236Sken sas = &cts->xport_specific.sas; 1068265236Sken scsi = &cts->proto_specific.scsi; 1069265236Sken 1070265236Sken KASSERT(cts->ccb_h.target_id < sassc->maxtargets, 1071265236Sken ("Target %d out of bounds in XPT_GET_TRAN_SETTINGS\n", 1072265236Sken cts->ccb_h.target_id)); 1073265236Sken targ = &sassc->targets[cts->ccb_h.target_id]; 1074265236Sken if (targ->handle == 0x0) { 1075283990Sslm mprsas_set_ccbstatus(ccb, CAM_DEV_NOT_THERE); 1076265236Sken break; 1077265236Sken } 1078265236Sken 1079265236Sken cts->protocol_version = SCSI_REV_SPC2; 1080265236Sken cts->transport = XPORT_SAS; 1081265236Sken cts->transport_version = 0; 1082265236Sken 1083265236Sken sas->valid = CTS_SAS_VALID_SPEED; 1084265236Sken switch (targ->linkrate) { 1085265236Sken case 0x08: 1086265236Sken sas->bitrate = 150000; 1087265236Sken break; 1088265236Sken case 0x09: 1089265236Sken sas->bitrate = 300000; 1090265236Sken break; 1091265236Sken case 0x0a: 1092265236Sken sas->bitrate = 600000; 1093265236Sken break; 1094273125Smav case 0x0b: 1095273125Smav sas->bitrate = 1200000; 1096273125Smav break; 1097265236Sken default: 1098265236Sken sas->valid = 0; 1099265236Sken } 1100265236Sken 1101265236Sken cts->protocol = PROTO_SCSI; 1102265236Sken scsi->valid = CTS_SCSI_VALID_TQ; 1103265236Sken scsi->flags = CTS_SCSI_FLAGS_TAG_ENB; 1104265236Sken 1105283990Sslm mprsas_set_ccbstatus(ccb, CAM_REQ_CMP); 1106265236Sken break; 1107265236Sken } 1108265236Sken case XPT_CALC_GEOMETRY: 1109265236Sken cam_calc_geometry(&ccb->ccg, /*extended*/1); 1110283990Sslm mprsas_set_ccbstatus(ccb, CAM_REQ_CMP); 1111265236Sken break; 1112265236Sken case XPT_RESET_DEV: 1113299962Sslm mpr_dprint(sassc->sc, MPR_XINFO, "mprsas_action " 1114299962Sslm "XPT_RESET_DEV\n"); 1115265236Sken mprsas_action_resetdev(sassc, ccb); 1116265236Sken return; 1117265236Sken case XPT_RESET_BUS: 1118265236Sken case XPT_ABORT: 1119265236Sken case XPT_TERM_IO: 1120299962Sslm mpr_dprint(sassc->sc, MPR_XINFO, "mprsas_action faking success " 1121299962Sslm "for abort or reset\n"); 1122283990Sslm mprsas_set_ccbstatus(ccb, CAM_REQ_CMP); 1123265236Sken break; 1124265236Sken case XPT_SCSI_IO: 1125265236Sken mprsas_action_scsiio(sassc, ccb); 1126265236Sken return; 1127265236Sken#if __FreeBSD_version >= 900026 1128265236Sken case XPT_SMP_IO: 1129265236Sken mprsas_action_smpio(sassc, ccb); 1130265236Sken return; 1131265236Sken#endif 1132265236Sken default: 1133283990Sslm mprsas_set_ccbstatus(ccb, CAM_FUNC_NOTAVAIL); 1134265236Sken break; 1135265236Sken } 1136265236Sken xpt_done(ccb); 1137265236Sken 1138265236Sken} 1139265236Sken 1140265236Skenstatic void 1141265236Skenmprsas_announce_reset(struct mpr_softc *sc, uint32_t ac_code, 1142265236Sken target_id_t target_id, lun_id_t lun_id) 1143265236Sken{ 1144265236Sken path_id_t path_id = cam_sim_path(sc->sassc->sim); 1145265236Sken struct cam_path *path; 1146265236Sken 1147265236Sken mpr_dprint(sc, MPR_XINFO, "%s code %x target %d lun %jx\n", __func__, 1148265236Sken ac_code, target_id, (uintmax_t)lun_id); 1149265236Sken 1150265236Sken if (xpt_create_path(&path, NULL, 1151265236Sken path_id, target_id, lun_id) != CAM_REQ_CMP) { 1152265236Sken mpr_dprint(sc, MPR_ERROR, "unable to create path for reset " 1153283990Sslm "notification\n"); 1154265236Sken return; 1155265236Sken } 1156265236Sken 1157265236Sken xpt_async(ac_code, path, NULL); 1158265236Sken xpt_free_path(path); 1159265236Sken} 1160265236Sken 1161265236Skenstatic void 1162265236Skenmprsas_complete_all_commands(struct mpr_softc *sc) 1163265236Sken{ 1164265236Sken struct mpr_command *cm; 1165265236Sken int i; 1166265236Sken int completed; 1167265236Sken 1168265236Sken MPR_FUNCTRACE(sc); 1169265236Sken mtx_assert(&sc->mpr_mtx, MA_OWNED); 1170265236Sken 1171265236Sken /* complete all commands with a NULL reply */ 1172265236Sken for (i = 1; i < sc->num_reqs; i++) { 1173265236Sken cm = &sc->commands[i]; 1174265236Sken cm->cm_reply = NULL; 1175265236Sken completed = 0; 1176265236Sken 1177265236Sken if (cm->cm_flags & MPR_CM_FLAGS_POLLED) 1178265236Sken cm->cm_flags |= MPR_CM_FLAGS_COMPLETE; 1179265236Sken 1180265236Sken if (cm->cm_complete != NULL) { 1181265236Sken mprsas_log_command(cm, MPR_RECOVERY, 1182299962Sslm "completing cm %p state %x ccb %p for diag reset\n", 1183299962Sslm cm, cm->cm_state, cm->cm_ccb); 1184265236Sken cm->cm_complete(sc, cm); 1185265236Sken completed = 1; 1186265236Sken } 1187265236Sken 1188265236Sken if (cm->cm_flags & MPR_CM_FLAGS_WAKEUP) { 1189265236Sken mprsas_log_command(cm, MPR_RECOVERY, 1190265236Sken "waking up cm %p state %x ccb %p for diag reset\n", 1191265236Sken cm, cm->cm_state, cm->cm_ccb); 1192265236Sken wakeup(cm); 1193265236Sken completed = 1; 1194265236Sken } 1195265236Sken 1196322661Sken if (cm->cm_sc->io_cmds_active != 0) 1197283990Sslm cm->cm_sc->io_cmds_active--; 1198283990Sslm 1199265236Sken if ((completed == 0) && (cm->cm_state != MPR_CM_STATE_FREE)) { 1200265236Sken /* this should never happen, but if it does, log */ 1201265236Sken mprsas_log_command(cm, MPR_RECOVERY, 1202265236Sken "cm %p state %x flags 0x%x ccb %p during diag " 1203265236Sken "reset\n", cm, cm->cm_state, cm->cm_flags, 1204265236Sken cm->cm_ccb); 1205265236Sken } 1206265236Sken } 1207265236Sken} 1208265236Sken 1209265236Skenvoid 1210265236Skenmprsas_handle_reinit(struct mpr_softc *sc) 1211265236Sken{ 1212265236Sken int i; 1213265236Sken 1214265236Sken /* Go back into startup mode and freeze the simq, so that CAM 1215265236Sken * doesn't send any commands until after we've rediscovered all 1216265236Sken * targets and found the proper device handles for them. 1217265236Sken * 1218265236Sken * After the reset, portenable will trigger discovery, and after all 1219265236Sken * discovery-related activities have finished, the simq will be 1220265236Sken * released. 1221265236Sken */ 1222265236Sken mpr_dprint(sc, MPR_INIT, "%s startup\n", __func__); 1223265236Sken sc->sassc->flags |= MPRSAS_IN_STARTUP; 1224265236Sken sc->sassc->flags |= MPRSAS_IN_DISCOVERY; 1225265236Sken mprsas_startup_increment(sc->sassc); 1226265236Sken 1227265236Sken /* notify CAM of a bus reset */ 1228265236Sken mprsas_announce_reset(sc, AC_BUS_RESET, CAM_TARGET_WILDCARD, 1229265236Sken CAM_LUN_WILDCARD); 1230265236Sken 1231265236Sken /* complete and cleanup after all outstanding commands */ 1232265236Sken mprsas_complete_all_commands(sc); 1233265236Sken 1234283990Sslm mpr_dprint(sc, MPR_INIT, "%s startup %u after command completion\n", 1235283990Sslm __func__, sc->sassc->startup_refcount); 1236265236Sken 1237265236Sken /* zero all the target handles, since they may change after the 1238265236Sken * reset, and we have to rediscover all the targets and use the new 1239265236Sken * handles. 1240265236Sken */ 1241265236Sken for (i = 0; i < sc->sassc->maxtargets; i++) { 1242265236Sken if (sc->sassc->targets[i].outstanding != 0) 1243265236Sken mpr_dprint(sc, MPR_INIT, "target %u outstanding %u\n", 1244265236Sken i, sc->sassc->targets[i].outstanding); 1245265236Sken sc->sassc->targets[i].handle = 0x0; 1246265236Sken sc->sassc->targets[i].exp_dev_handle = 0x0; 1247265236Sken sc->sassc->targets[i].outstanding = 0; 1248265236Sken sc->sassc->targets[i].flags = MPRSAS_TARGET_INDIAGRESET; 1249265236Sken } 1250265236Sken} 1251265236Skenstatic void 1252265236Skenmprsas_tm_timeout(void *data) 1253265236Sken{ 1254265236Sken struct mpr_command *tm = data; 1255265236Sken struct mpr_softc *sc = tm->cm_sc; 1256265236Sken 1257265236Sken mtx_assert(&sc->mpr_mtx, MA_OWNED); 1258265236Sken 1259299962Sslm mprsas_log_command(tm, MPR_INFO|MPR_RECOVERY, "task mgmt %p timed " 1260299962Sslm "out\n", tm); 1261265236Sken mpr_reinit(sc); 1262265236Sken} 1263265236Sken 1264265236Skenstatic void 1265299962Sslmmprsas_logical_unit_reset_complete(struct mpr_softc *sc, struct mpr_command *tm) 1266265236Sken{ 1267265236Sken MPI2_SCSI_TASK_MANAGE_REPLY *reply; 1268265236Sken MPI2_SCSI_TASK_MANAGE_REQUEST *req; 1269265236Sken unsigned int cm_count = 0; 1270265236Sken struct mpr_command *cm; 1271265236Sken struct mprsas_target *targ; 1272265236Sken 1273265236Sken callout_stop(&tm->cm_callout); 1274265236Sken 1275265236Sken req = (MPI2_SCSI_TASK_MANAGE_REQUEST *)tm->cm_req; 1276265236Sken reply = (MPI2_SCSI_TASK_MANAGE_REPLY *)tm->cm_reply; 1277265236Sken targ = tm->cm_targ; 1278265236Sken 1279265236Sken /* 1280265236Sken * Currently there should be no way we can hit this case. It only 1281265236Sken * happens when we have a failure to allocate chain frames, and 1282265236Sken * task management commands don't have S/G lists. 1283265236Sken */ 1284265236Sken if ((tm->cm_flags & MPR_CM_FLAGS_ERROR_MASK) != 0) { 1285265236Sken mpr_dprint(sc, MPR_ERROR, "%s: cm_flags = %#x for LUN reset! " 1286265236Sken "This should not happen!\n", __func__, tm->cm_flags); 1287265236Sken mprsas_free_tm(sc, tm); 1288265236Sken return; 1289265236Sken } 1290265236Sken 1291265236Sken if (reply == NULL) { 1292299962Sslm mprsas_log_command(tm, MPR_RECOVERY, "NULL reset reply for tm " 1293299962Sslm "%p\n", tm); 1294265236Sken if ((sc->mpr_flags & MPR_FLAGS_DIAGRESET) != 0) { 1295265236Sken /* this completion was due to a reset, just cleanup */ 1296265236Sken targ->tm = NULL; 1297265236Sken mprsas_free_tm(sc, tm); 1298265236Sken } 1299265236Sken else { 1300265236Sken /* we should have gotten a reply. */ 1301265236Sken mpr_reinit(sc); 1302265236Sken } 1303265236Sken return; 1304265236Sken } 1305265236Sken 1306265236Sken mprsas_log_command(tm, MPR_RECOVERY, 1307265236Sken "logical unit reset status 0x%x code 0x%x count %u\n", 1308265236Sken le16toh(reply->IOCStatus), le32toh(reply->ResponseCode), 1309265236Sken le32toh(reply->TerminationCount)); 1310265236Sken 1311265236Sken /* See if there are any outstanding commands for this LUN. 1312265236Sken * This could be made more efficient by using a per-LU data 1313265236Sken * structure of some sort. 1314265236Sken */ 1315265236Sken TAILQ_FOREACH(cm, &targ->commands, cm_link) { 1316265236Sken if (cm->cm_lun == tm->cm_lun) 1317265236Sken cm_count++; 1318265236Sken } 1319265236Sken 1320265236Sken if (cm_count == 0) { 1321265236Sken mprsas_log_command(tm, MPR_RECOVERY|MPR_INFO, 1322265236Sken "logical unit %u finished recovery after reset\n", 1323265236Sken tm->cm_lun, tm); 1324265236Sken 1325265236Sken mprsas_announce_reset(sc, AC_SENT_BDR, tm->cm_targ->tid, 1326265236Sken tm->cm_lun); 1327265236Sken 1328265236Sken /* we've finished recovery for this logical unit. check and 1329265236Sken * see if some other logical unit has a timedout command 1330265236Sken * that needs to be processed. 1331265236Sken */ 1332265236Sken cm = TAILQ_FIRST(&targ->timedout_commands); 1333265236Sken if (cm) { 1334265236Sken mprsas_send_abort(sc, tm, cm); 1335265236Sken } 1336265236Sken else { 1337265236Sken targ->tm = NULL; 1338265236Sken mprsas_free_tm(sc, tm); 1339265236Sken } 1340265236Sken } 1341265236Sken else { 1342265236Sken /* if we still have commands for this LUN, the reset 1343265236Sken * effectively failed, regardless of the status reported. 1344265236Sken * Escalate to a target reset. 1345265236Sken */ 1346265236Sken mprsas_log_command(tm, MPR_RECOVERY, 1347265236Sken "logical unit reset complete for tm %p, but still have %u " 1348265236Sken "command(s)\n", tm, cm_count); 1349265236Sken mprsas_send_reset(sc, tm, 1350265236Sken MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET); 1351265236Sken } 1352265236Sken} 1353265236Sken 1354265236Skenstatic void 1355265236Skenmprsas_target_reset_complete(struct mpr_softc *sc, struct mpr_command *tm) 1356265236Sken{ 1357265236Sken MPI2_SCSI_TASK_MANAGE_REPLY *reply; 1358265236Sken MPI2_SCSI_TASK_MANAGE_REQUEST *req; 1359265236Sken struct mprsas_target *targ; 1360265236Sken 1361265236Sken callout_stop(&tm->cm_callout); 1362265236Sken 1363265236Sken req = (MPI2_SCSI_TASK_MANAGE_REQUEST *)tm->cm_req; 1364265236Sken reply = (MPI2_SCSI_TASK_MANAGE_REPLY *)tm->cm_reply; 1365265236Sken targ = tm->cm_targ; 1366265236Sken 1367265236Sken /* 1368265236Sken * Currently there should be no way we can hit this case. It only 1369265236Sken * happens when we have a failure to allocate chain frames, and 1370265236Sken * task management commands don't have S/G lists. 1371265236Sken */ 1372265236Sken if ((tm->cm_flags & MPR_CM_FLAGS_ERROR_MASK) != 0) { 1373283990Sslm mpr_dprint(sc, MPR_ERROR, "%s: cm_flags = %#x for target " 1374283990Sslm "reset! This should not happen!\n", __func__, tm->cm_flags); 1375265236Sken mprsas_free_tm(sc, tm); 1376265236Sken return; 1377265236Sken } 1378265236Sken 1379265236Sken if (reply == NULL) { 1380299962Sslm mprsas_log_command(tm, MPR_RECOVERY, "NULL reset reply for tm " 1381299962Sslm "%p\n", tm); 1382265236Sken if ((sc->mpr_flags & MPR_FLAGS_DIAGRESET) != 0) { 1383265236Sken /* this completion was due to a reset, just cleanup */ 1384265236Sken targ->tm = NULL; 1385265236Sken mprsas_free_tm(sc, tm); 1386265236Sken } 1387265236Sken else { 1388265236Sken /* we should have gotten a reply. */ 1389265236Sken mpr_reinit(sc); 1390265236Sken } 1391265236Sken return; 1392265236Sken } 1393265236Sken 1394265236Sken mprsas_log_command(tm, MPR_RECOVERY, 1395265236Sken "target reset status 0x%x code 0x%x count %u\n", 1396265236Sken le16toh(reply->IOCStatus), le32toh(reply->ResponseCode), 1397265236Sken le32toh(reply->TerminationCount)); 1398265236Sken 1399265236Sken if (targ->outstanding == 0) { 1400265236Sken /* we've finished recovery for this target and all 1401265236Sken * of its logical units. 1402265236Sken */ 1403265236Sken mprsas_log_command(tm, MPR_RECOVERY|MPR_INFO, 1404265236Sken "recovery finished after target reset\n"); 1405265236Sken 1406265236Sken mprsas_announce_reset(sc, AC_SENT_BDR, tm->cm_targ->tid, 1407265236Sken CAM_LUN_WILDCARD); 1408265236Sken 1409265236Sken targ->tm = NULL; 1410265236Sken mprsas_free_tm(sc, tm); 1411265236Sken } 1412265236Sken else { 1413265236Sken /* after a target reset, if this target still has 1414265236Sken * outstanding commands, the reset effectively failed, 1415265236Sken * regardless of the status reported. escalate. 1416265236Sken */ 1417265236Sken mprsas_log_command(tm, MPR_RECOVERY, 1418265236Sken "target reset complete for tm %p, but still have %u " 1419265236Sken "command(s)\n", tm, targ->outstanding); 1420265236Sken mpr_reinit(sc); 1421265236Sken } 1422265236Sken} 1423265236Sken 1424265236Sken#define MPR_RESET_TIMEOUT 30 1425265236Sken 1426283990Sslmint 1427265236Skenmprsas_send_reset(struct mpr_softc *sc, struct mpr_command *tm, uint8_t type) 1428265236Sken{ 1429265236Sken MPI2_SCSI_TASK_MANAGE_REQUEST *req; 1430265236Sken struct mprsas_target *target; 1431265236Sken int err; 1432265236Sken 1433265236Sken target = tm->cm_targ; 1434265236Sken if (target->handle == 0) { 1435283990Sslm mpr_dprint(sc, MPR_ERROR, "%s null devhandle for target_id " 1436283990Sslm "%d\n", __func__, target->tid); 1437265236Sken return -1; 1438265236Sken } 1439265236Sken 1440265236Sken req = (MPI2_SCSI_TASK_MANAGE_REQUEST *)tm->cm_req; 1441265236Sken req->DevHandle = htole16(target->handle); 1442265236Sken req->Function = MPI2_FUNCTION_SCSI_TASK_MGMT; 1443265236Sken req->TaskType = type; 1444265236Sken 1445265236Sken if (type == MPI2_SCSITASKMGMT_TASKTYPE_LOGICAL_UNIT_RESET) { 1446265236Sken /* XXX Need to handle invalid LUNs */ 1447265236Sken MPR_SET_LUN(req->LUN, tm->cm_lun); 1448265236Sken tm->cm_targ->logical_unit_resets++; 1449265236Sken mprsas_log_command(tm, MPR_RECOVERY|MPR_INFO, 1450265236Sken "sending logical unit reset\n"); 1451265236Sken tm->cm_complete = mprsas_logical_unit_reset_complete; 1452283990Sslm mprsas_prepare_for_tm(sc, tm, target, tm->cm_lun); 1453265236Sken } 1454265236Sken else if (type == MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET) { 1455265236Sken /* 1456265236Sken * Target reset method = 1457265236Sken * SAS Hard Link Reset / SATA Link Reset 1458265236Sken */ 1459265236Sken req->MsgFlags = MPI2_SCSITASKMGMT_MSGFLAGS_LINK_RESET; 1460265236Sken tm->cm_targ->target_resets++; 1461265236Sken mprsas_log_command(tm, MPR_RECOVERY|MPR_INFO, 1462265236Sken "sending target reset\n"); 1463265236Sken tm->cm_complete = mprsas_target_reset_complete; 1464283990Sslm mprsas_prepare_for_tm(sc, tm, target, CAM_LUN_WILDCARD); 1465265236Sken } 1466265236Sken else { 1467265236Sken mpr_dprint(sc, MPR_ERROR, "unexpected reset type 0x%x\n", type); 1468265236Sken return -1; 1469265236Sken } 1470265236Sken 1471283990Sslm mpr_dprint(sc, MPR_INFO, "to target %u handle 0x%04x\n", target->tid, 1472265236Sken target->handle); 1473265236Sken if (target->encl_level_valid) { 1474283990Sslm mpr_dprint(sc, MPR_INFO, "At enclosure level %d, slot %d, " 1475265236Sken "connector name (%4s)\n", target->encl_level, 1476265236Sken target->encl_slot, target->connector_name); 1477265236Sken } 1478265236Sken 1479265236Sken tm->cm_data = NULL; 1480265236Sken tm->cm_desc.HighPriority.RequestFlags = 1481265236Sken MPI2_REQ_DESCRIPT_FLAGS_HIGH_PRIORITY; 1482265236Sken tm->cm_complete_data = (void *)tm; 1483265236Sken 1484265236Sken callout_reset(&tm->cm_callout, MPR_RESET_TIMEOUT * hz, 1485265236Sken mprsas_tm_timeout, tm); 1486265236Sken 1487265236Sken err = mpr_map_command(sc, tm); 1488265236Sken if (err) 1489265236Sken mprsas_log_command(tm, MPR_RECOVERY, 1490283990Sslm "error %d sending reset type %u\n", err, type); 1491265236Sken 1492265236Sken return err; 1493265236Sken} 1494265236Sken 1495265236Sken 1496265236Skenstatic void 1497265236Skenmprsas_abort_complete(struct mpr_softc *sc, struct mpr_command *tm) 1498265236Sken{ 1499265236Sken struct mpr_command *cm; 1500265236Sken MPI2_SCSI_TASK_MANAGE_REPLY *reply; 1501265236Sken MPI2_SCSI_TASK_MANAGE_REQUEST *req; 1502265236Sken struct mprsas_target *targ; 1503265236Sken 1504265236Sken callout_stop(&tm->cm_callout); 1505265236Sken 1506265236Sken req = (MPI2_SCSI_TASK_MANAGE_REQUEST *)tm->cm_req; 1507265236Sken reply = (MPI2_SCSI_TASK_MANAGE_REPLY *)tm->cm_reply; 1508265236Sken targ = tm->cm_targ; 1509265236Sken 1510265236Sken /* 1511265236Sken * Currently there should be no way we can hit this case. It only 1512265236Sken * happens when we have a failure to allocate chain frames, and 1513265236Sken * task management commands don't have S/G lists. 1514265236Sken */ 1515265236Sken if ((tm->cm_flags & MPR_CM_FLAGS_ERROR_MASK) != 0) { 1516265236Sken mprsas_log_command(tm, MPR_RECOVERY, 1517265236Sken "cm_flags = %#x for abort %p TaskMID %u!\n", 1518265236Sken tm->cm_flags, tm, le16toh(req->TaskMID)); 1519265236Sken mprsas_free_tm(sc, tm); 1520265236Sken return; 1521265236Sken } 1522265236Sken 1523265236Sken if (reply == NULL) { 1524265236Sken mprsas_log_command(tm, MPR_RECOVERY, 1525265236Sken "NULL abort reply for tm %p TaskMID %u\n", 1526265236Sken tm, le16toh(req->TaskMID)); 1527265236Sken if ((sc->mpr_flags & MPR_FLAGS_DIAGRESET) != 0) { 1528265236Sken /* this completion was due to a reset, just cleanup */ 1529265236Sken targ->tm = NULL; 1530265236Sken mprsas_free_tm(sc, tm); 1531265236Sken } 1532265236Sken else { 1533265236Sken /* we should have gotten a reply. */ 1534265236Sken mpr_reinit(sc); 1535265236Sken } 1536265236Sken return; 1537265236Sken } 1538265236Sken 1539265236Sken mprsas_log_command(tm, MPR_RECOVERY, 1540265236Sken "abort TaskMID %u status 0x%x code 0x%x count %u\n", 1541265236Sken le16toh(req->TaskMID), 1542265236Sken le16toh(reply->IOCStatus), le32toh(reply->ResponseCode), 1543265236Sken le32toh(reply->TerminationCount)); 1544265236Sken 1545265236Sken cm = TAILQ_FIRST(&tm->cm_targ->timedout_commands); 1546265236Sken if (cm == NULL) { 1547265236Sken /* if there are no more timedout commands, we're done with 1548265236Sken * error recovery for this target. 1549265236Sken */ 1550265236Sken mprsas_log_command(tm, MPR_RECOVERY, 1551265236Sken "finished recovery after aborting TaskMID %u\n", 1552265236Sken le16toh(req->TaskMID)); 1553265236Sken 1554265236Sken targ->tm = NULL; 1555265236Sken mprsas_free_tm(sc, tm); 1556265236Sken } 1557265236Sken else if (le16toh(req->TaskMID) != cm->cm_desc.Default.SMID) { 1558265236Sken /* abort success, but we have more timedout commands to abort */ 1559265236Sken mprsas_log_command(tm, MPR_RECOVERY, 1560265236Sken "continuing recovery after aborting TaskMID %u\n", 1561265236Sken le16toh(req->TaskMID)); 1562265236Sken 1563265236Sken mprsas_send_abort(sc, tm, cm); 1564265236Sken } 1565265236Sken else { 1566265236Sken /* we didn't get a command completion, so the abort 1567265236Sken * failed as far as we're concerned. escalate. 1568265236Sken */ 1569265236Sken mprsas_log_command(tm, MPR_RECOVERY, 1570265236Sken "abort failed for TaskMID %u tm %p\n", 1571265236Sken le16toh(req->TaskMID), tm); 1572265236Sken 1573265236Sken mprsas_send_reset(sc, tm, 1574265236Sken MPI2_SCSITASKMGMT_TASKTYPE_LOGICAL_UNIT_RESET); 1575265236Sken } 1576265236Sken} 1577265236Sken 1578265236Sken#define MPR_ABORT_TIMEOUT 5 1579265236Sken 1580265236Skenstatic int 1581265236Skenmprsas_send_abort(struct mpr_softc *sc, struct mpr_command *tm, 1582265236Sken struct mpr_command *cm) 1583265236Sken{ 1584265236Sken MPI2_SCSI_TASK_MANAGE_REQUEST *req; 1585265236Sken struct mprsas_target *targ; 1586265236Sken int err; 1587265236Sken 1588265236Sken targ = cm->cm_targ; 1589265236Sken if (targ->handle == 0) { 1590265236Sken mpr_dprint(sc, MPR_ERROR,"%s null devhandle for target_id %d\n", 1591265236Sken __func__, cm->cm_ccb->ccb_h.target_id); 1592265236Sken return -1; 1593265236Sken } 1594265236Sken 1595319436Sslm mprsas_log_command(cm, MPR_RECOVERY|MPR_INFO, 1596265236Sken "Aborting command %p\n", cm); 1597265236Sken 1598265236Sken req = (MPI2_SCSI_TASK_MANAGE_REQUEST *)tm->cm_req; 1599265236Sken req->DevHandle = htole16(targ->handle); 1600265236Sken req->Function = MPI2_FUNCTION_SCSI_TASK_MGMT; 1601265236Sken req->TaskType = MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK; 1602265236Sken 1603265236Sken /* XXX Need to handle invalid LUNs */ 1604265236Sken MPR_SET_LUN(req->LUN, cm->cm_ccb->ccb_h.target_lun); 1605265236Sken 1606265236Sken req->TaskMID = htole16(cm->cm_desc.Default.SMID); 1607265236Sken 1608265236Sken tm->cm_data = NULL; 1609265236Sken tm->cm_desc.HighPriority.RequestFlags = 1610265236Sken MPI2_REQ_DESCRIPT_FLAGS_HIGH_PRIORITY; 1611265236Sken tm->cm_complete = mprsas_abort_complete; 1612265236Sken tm->cm_complete_data = (void *)tm; 1613265236Sken tm->cm_targ = cm->cm_targ; 1614265236Sken tm->cm_lun = cm->cm_lun; 1615265236Sken 1616265236Sken callout_reset(&tm->cm_callout, MPR_ABORT_TIMEOUT * hz, 1617265236Sken mprsas_tm_timeout, tm); 1618265236Sken 1619265236Sken targ->aborts++; 1620265236Sken 1621283990Sslm mpr_dprint(sc, MPR_INFO, "Sending reset from %s for target ID %d\n", 1622283990Sslm __func__, targ->tid); 1623283990Sslm mprsas_prepare_for_tm(sc, tm, targ, tm->cm_lun); 1624283990Sslm 1625265236Sken err = mpr_map_command(sc, tm); 1626265236Sken if (err) 1627319436Sslm mpr_dprint(sc, MPR_RECOVERY, 1628265236Sken "error %d sending abort for cm %p SMID %u\n", 1629265236Sken err, cm, req->TaskMID); 1630265236Sken return err; 1631265236Sken} 1632265236Sken 1633265236Skenstatic void 1634265236Skenmprsas_scsiio_timeout(void *data) 1635265236Sken{ 1636265236Sken struct mpr_softc *sc; 1637265236Sken struct mpr_command *cm; 1638265236Sken struct mprsas_target *targ; 1639265236Sken 1640265236Sken cm = (struct mpr_command *)data; 1641265236Sken sc = cm->cm_sc; 1642265236Sken 1643265236Sken MPR_FUNCTRACE(sc); 1644265236Sken mtx_assert(&sc->mpr_mtx, MA_OWNED); 1645265236Sken 1646265236Sken mpr_dprint(sc, MPR_XINFO, "Timeout checking cm %p\n", cm); 1647265236Sken 1648265236Sken /* 1649265236Sken * Run the interrupt handler to make sure it's not pending. This 1650265236Sken * isn't perfect because the command could have already completed 1651265236Sken * and been re-used, though this is unlikely. 1652265236Sken */ 1653265236Sken mpr_intr_locked(sc); 1654265236Sken if (cm->cm_state == MPR_CM_STATE_FREE) { 1655265236Sken mprsas_log_command(cm, MPR_XINFO, 1656265236Sken "SCSI command %p almost timed out\n", cm); 1657265236Sken return; 1658265236Sken } 1659265236Sken 1660265236Sken if (cm->cm_ccb == NULL) { 1661265236Sken mpr_dprint(sc, MPR_ERROR, "command timeout with NULL ccb\n"); 1662265236Sken return; 1663265236Sken } 1664265236Sken 1665265236Sken targ = cm->cm_targ; 1666265236Sken targ->timeouts++; 1667265236Sken 1668319436Sslm mprsas_log_command(cm, MPR_ERROR, "command timeout %d cm %p target " 1669319436Sslm "%u, handle(0x%04x)\n", cm->cm_ccb->ccb_h.timeout, cm, targ->tid, 1670319436Sslm targ->handle); 1671265236Sken if (targ->encl_level_valid) { 1672283990Sslm mpr_dprint(sc, MPR_ERROR, "At enclosure level %d, slot %d, " 1673265236Sken "connector name (%4s)\n", targ->encl_level, targ->encl_slot, 1674265236Sken targ->connector_name); 1675265236Sken } 1676265236Sken 1677265236Sken /* XXX first, check the firmware state, to see if it's still 1678265236Sken * operational. if not, do a diag reset. 1679265236Sken */ 1680283990Sslm mprsas_set_ccbstatus(cm->cm_ccb, CAM_CMD_TIMEOUT); 1681265236Sken cm->cm_state = MPR_CM_STATE_TIMEDOUT; 1682265236Sken TAILQ_INSERT_TAIL(&targ->timedout_commands, cm, cm_recovery); 1683265236Sken 1684265236Sken if (targ->tm != NULL) { 1685265236Sken /* target already in recovery, just queue up another 1686265236Sken * timedout command to be processed later. 1687265236Sken */ 1688265236Sken mpr_dprint(sc, MPR_RECOVERY, "queued timedout cm %p for " 1689265236Sken "processing by tm %p\n", cm, targ->tm); 1690265236Sken } 1691265236Sken else if ((targ->tm = mprsas_alloc_tm(sc)) != NULL) { 1692265236Sken mpr_dprint(sc, MPR_RECOVERY, "timedout cm %p allocated tm %p\n", 1693265236Sken cm, targ->tm); 1694265236Sken 1695265236Sken /* start recovery by aborting the first timedout command */ 1696265236Sken mprsas_send_abort(sc, targ->tm, cm); 1697265236Sken } 1698265236Sken else { 1699265236Sken /* XXX queue this target up for recovery once a TM becomes 1700265236Sken * available. The firmware only has a limited number of 1701265236Sken * HighPriority credits for the high priority requests used 1702265236Sken * for task management, and we ran out. 1703265236Sken * 1704265236Sken * Isilon: don't worry about this for now, since we have 1705265236Sken * more credits than disks in an enclosure, and limit 1706265236Sken * ourselves to one TM per target for recovery. 1707265236Sken */ 1708299962Sslm mpr_dprint(sc, MPR_RECOVERY, "timedout cm %p failed to " 1709299962Sslm "allocate a tm\n", cm); 1710265236Sken } 1711265236Sken} 1712265236Sken 1713319436Sslm/** 1714319436Sslm * mprsas_build_nvme_unmap - Build Native NVMe DSM command equivalent 1715319436Sslm * to SCSI Unmap. 1716319436Sslm * Return 0 - for success, 1717319436Sslm * 1 - to immediately return back the command with success status to CAM 1718319436Sslm * negative value - to fallback to firmware path i.e. issue scsi unmap 1719319436Sslm * to FW without any translation. 1720319436Sslm */ 1721319436Sslmstatic int 1722319436Sslmmprsas_build_nvme_unmap(struct mpr_softc *sc, struct mpr_command *cm, 1723319436Sslm union ccb *ccb, struct mprsas_target *targ) 1724319436Sslm{ 1725319436Sslm Mpi26NVMeEncapsulatedRequest_t *req = NULL; 1726319436Sslm struct ccb_scsiio *csio; 1727319436Sslm struct unmap_parm_list *plist; 1728319436Sslm struct nvme_dsm_range *nvme_dsm_ranges = NULL; 1729319436Sslm struct nvme_command *c; 1730319436Sslm int i, res; 1731319436Sslm uint16_t ndesc, list_len, data_length; 1732319436Sslm struct mpr_prp_page *prp_page_info; 1733319436Sslm uint64_t nvme_dsm_ranges_dma_handle; 1734319436Sslm 1735319436Sslm csio = &ccb->csio; 1736319436Sslm#if __FreeBSD_version >= 1100103 1737319436Sslm list_len = (scsiio_cdb_ptr(csio)[7] << 8 | scsiio_cdb_ptr(csio)[8]); 1738319436Sslm#else 1739319436Sslm if (csio->ccb_h.flags & CAM_CDB_POINTER) { 1740319436Sslm list_len = (ccb->csio.cdb_io.cdb_ptr[7] << 8 | 1741319436Sslm ccb->csio.cdb_io.cdb_ptr[8]); 1742319436Sslm } else { 1743319436Sslm list_len = (ccb->csio.cdb_io.cdb_bytes[7] << 8 | 1744319436Sslm ccb->csio.cdb_io.cdb_bytes[8]); 1745319436Sslm } 1746319436Sslm#endif 1747319436Sslm if (!list_len) { 1748319436Sslm mpr_dprint(sc, MPR_ERROR, "Parameter list length is Zero\n"); 1749319436Sslm return -EINVAL; 1750319436Sslm } 1751319436Sslm 1752319436Sslm plist = malloc(csio->dxfer_len, M_MPR, M_ZERO|M_NOWAIT); 1753319436Sslm if (!plist) { 1754319436Sslm mpr_dprint(sc, MPR_ERROR, "Unable to allocate memory to " 1755319436Sslm "save UNMAP data\n"); 1756319436Sslm return -ENOMEM; 1757319436Sslm } 1758319436Sslm 1759319436Sslm /* Copy SCSI unmap data to a local buffer */ 1760319436Sslm bcopy(csio->data_ptr, plist, csio->dxfer_len); 1761319436Sslm 1762319436Sslm /* return back the unmap command to CAM with success status, 1763319436Sslm * if number of descripts is zero. 1764319436Sslm */ 1765319436Sslm ndesc = be16toh(plist->unmap_blk_desc_data_len) >> 4; 1766319436Sslm if (!ndesc) { 1767319436Sslm mpr_dprint(sc, MPR_XINFO, "Number of descriptors in " 1768319436Sslm "UNMAP cmd is Zero\n"); 1769319436Sslm res = 1; 1770319436Sslm goto out; 1771319436Sslm } 1772319436Sslm 1773319436Sslm data_length = ndesc * sizeof(struct nvme_dsm_range); 1774319436Sslm if (data_length > targ->MDTS) { 1775319436Sslm mpr_dprint(sc, MPR_ERROR, "data length: %d is greater than " 1776319436Sslm "Device's MDTS: %d\n", data_length, targ->MDTS); 1777319436Sslm res = -EINVAL; 1778319436Sslm goto out; 1779319436Sslm } 1780319436Sslm 1781319436Sslm prp_page_info = mpr_alloc_prp_page(sc); 1782319436Sslm KASSERT(prp_page_info != NULL, ("%s: There is no PRP Page for " 1783319436Sslm "UNMAP command.\n", __func__)); 1784319436Sslm 1785319436Sslm /* 1786319436Sslm * Insert the allocated PRP page into the command's PRP page list. This 1787319436Sslm * will be freed when the command is freed. 1788319436Sslm */ 1789319436Sslm TAILQ_INSERT_TAIL(&cm->cm_prp_page_list, prp_page_info, prp_page_link); 1790319436Sslm 1791319436Sslm nvme_dsm_ranges = (struct nvme_dsm_range *)prp_page_info->prp_page; 1792319436Sslm nvme_dsm_ranges_dma_handle = prp_page_info->prp_page_busaddr; 1793319436Sslm 1794319436Sslm bzero(nvme_dsm_ranges, data_length); 1795319436Sslm 1796319436Sslm /* Convert SCSI unmap's descriptor data to NVMe DSM specific Range data 1797319436Sslm * for each descriptors contained in SCSI UNMAP data. 1798319436Sslm */ 1799319436Sslm for (i = 0; i < ndesc; i++) { 1800319436Sslm nvme_dsm_ranges[i].length = 1801319436Sslm htole32(be32toh(plist->desc[i].nlb)); 1802319436Sslm nvme_dsm_ranges[i].starting_lba = 1803319436Sslm htole64(be64toh(plist->desc[i].slba)); 1804319436Sslm nvme_dsm_ranges[i].attributes = 0; 1805319436Sslm } 1806319436Sslm 1807319436Sslm /* Build MPI2.6's NVMe Encapsulated Request Message */ 1808319436Sslm req = (Mpi26NVMeEncapsulatedRequest_t *)cm->cm_req; 1809319436Sslm bzero(req, sizeof(*req)); 1810319436Sslm req->DevHandle = htole16(targ->handle); 1811319436Sslm req->Function = MPI2_FUNCTION_NVME_ENCAPSULATED; 1812319436Sslm req->Flags = MPI26_NVME_FLAGS_WRITE; 1813319436Sslm req->ErrorResponseBaseAddress.High = 1814319436Sslm htole32((uint32_t)((uint64_t)cm->cm_sense_busaddr >> 32)); 1815319436Sslm req->ErrorResponseBaseAddress.Low = 1816319436Sslm htole32(cm->cm_sense_busaddr); 1817319436Sslm req->ErrorResponseAllocationLength = 1818319436Sslm htole16(sizeof(struct nvme_completion)); 1819319436Sslm req->EncapsulatedCommandLength = 1820319436Sslm htole16(sizeof(struct nvme_command)); 1821319436Sslm req->DataLength = htole32(data_length); 1822319436Sslm 1823319436Sslm /* Build NVMe DSM command */ 1824319436Sslm c = (struct nvme_command *) req->NVMe_Command; 1825319436Sslm c->opc = NVME_OPC_DATASET_MANAGEMENT; 1826319436Sslm c->nsid = htole32(csio->ccb_h.target_lun + 1); 1827319436Sslm c->cdw10 = htole32(ndesc - 1); 1828319436Sslm c->cdw11 = htole32(NVME_DSM_ATTR_DEALLOCATE); 1829319436Sslm 1830319436Sslm cm->cm_length = data_length; 1831319436Sslm cm->cm_data = NULL; 1832319436Sslm 1833319436Sslm cm->cm_complete = mprsas_scsiio_complete; 1834319436Sslm cm->cm_complete_data = ccb; 1835319436Sslm cm->cm_targ = targ; 1836319436Sslm cm->cm_lun = csio->ccb_h.target_lun; 1837319436Sslm cm->cm_ccb = ccb; 1838319436Sslm 1839319436Sslm cm->cm_desc.Default.RequestFlags = 1840319436Sslm MPI26_REQ_DESCRIPT_FLAGS_PCIE_ENCAPSULATED; 1841319436Sslm 1842319436Sslm#if __FreeBSD_version >= 1000029 1843319436Sslm callout_reset_sbt(&cm->cm_callout, SBT_1MS * ccb->ccb_h.timeout, 0, 1844319436Sslm mprsas_scsiio_timeout, cm, 0); 1845319436Sslm#else //__FreeBSD_version < 1000029 1846319436Sslm callout_reset(&cm->cm_callout, (ccb->ccb_h.timeout * hz) / 1000, 1847319436Sslm mprsas_scsiio_timeout, cm); 1848319436Sslm#endif //__FreeBSD_version >= 1000029 1849319436Sslm 1850319436Sslm targ->issued++; 1851319436Sslm targ->outstanding++; 1852319436Sslm TAILQ_INSERT_TAIL(&targ->commands, cm, cm_link); 1853319436Sslm ccb->ccb_h.status |= CAM_SIM_QUEUED; 1854319436Sslm 1855319436Sslm mprsas_log_command(cm, MPR_XINFO, "%s cm %p ccb %p outstanding %u\n", 1856319436Sslm __func__, cm, ccb, targ->outstanding); 1857319436Sslm 1858319436Sslm mpr_build_nvme_prp(sc, cm, req, 1859319436Sslm (void *)(uintptr_t)nvme_dsm_ranges_dma_handle, 0, data_length); 1860319436Sslm mpr_map_command(sc, cm); 1861319436Sslm 1862319436Sslmout: 1863319436Sslm free(plist, M_MPR); 1864319436Sslm return 0; 1865319436Sslm} 1866319436Sslm 1867265236Skenstatic void 1868265236Skenmprsas_action_scsiio(struct mprsas_softc *sassc, union ccb *ccb) 1869265236Sken{ 1870265236Sken MPI2_SCSI_IO_REQUEST *req; 1871265236Sken struct ccb_scsiio *csio; 1872265236Sken struct mpr_softc *sc; 1873265236Sken struct mprsas_target *targ; 1874265236Sken struct mprsas_lun *lun; 1875265236Sken struct mpr_command *cm; 1876319436Sslm uint8_t i, lba_byte, *ref_tag_addr, scsi_opcode; 1877265236Sken uint16_t eedp_flags; 1878265236Sken uint32_t mpi_control; 1879319436Sslm int rc; 1880265236Sken 1881265236Sken sc = sassc->sc; 1882265236Sken MPR_FUNCTRACE(sc); 1883265236Sken mtx_assert(&sc->mpr_mtx, MA_OWNED); 1884265236Sken 1885265236Sken csio = &ccb->csio; 1886283990Sslm KASSERT(csio->ccb_h.target_id < sassc->maxtargets, 1887283990Sslm ("Target %d out of bounds in XPT_SCSI_IO\n", 1888283990Sslm csio->ccb_h.target_id)); 1889265236Sken targ = &sassc->targets[csio->ccb_h.target_id]; 1890265236Sken mpr_dprint(sc, MPR_TRACE, "ccb %p target flag %x\n", ccb, targ->flags); 1891265236Sken if (targ->handle == 0x0) { 1892265236Sken mpr_dprint(sc, MPR_ERROR, "%s NULL handle for target %u\n", 1893265236Sken __func__, csio->ccb_h.target_id); 1894283990Sslm mprsas_set_ccbstatus(ccb, CAM_DEV_NOT_THERE); 1895265236Sken xpt_done(ccb); 1896265236Sken return; 1897265236Sken } 1898265236Sken if (targ->flags & MPR_TARGET_FLAGS_RAID_COMPONENT) { 1899283990Sslm mpr_dprint(sc, MPR_ERROR, "%s Raid component no SCSI IO " 1900265236Sken "supported %u\n", __func__, csio->ccb_h.target_id); 1901283990Sslm mprsas_set_ccbstatus(ccb, CAM_DEV_NOT_THERE); 1902265236Sken xpt_done(ccb); 1903265236Sken return; 1904265236Sken } 1905265236Sken /* 1906265236Sken * Sometimes, it is possible to get a command that is not "In 1907265236Sken * Progress" and was actually aborted by the upper layer. Check for 1908265236Sken * this here and complete the command without error. 1909265236Sken */ 1910283990Sslm if (mprsas_get_ccbstatus(ccb) != CAM_REQ_INPROG) { 1911265236Sken mpr_dprint(sc, MPR_TRACE, "%s Command is not in progress for " 1912265236Sken "target %u\n", __func__, csio->ccb_h.target_id); 1913265236Sken xpt_done(ccb); 1914265236Sken return; 1915265236Sken } 1916265236Sken /* 1917265236Sken * If devinfo is 0 this will be a volume. In that case don't tell CAM 1918265236Sken * that the volume has timed out. We want volumes to be enumerated 1919265236Sken * until they are deleted/removed, not just failed. 1920265236Sken */ 1921265236Sken if (targ->flags & MPRSAS_TARGET_INREMOVAL) { 1922265236Sken if (targ->devinfo == 0) 1923283990Sslm mprsas_set_ccbstatus(ccb, CAM_REQ_CMP); 1924265236Sken else 1925283990Sslm mprsas_set_ccbstatus(ccb, CAM_SEL_TIMEOUT); 1926265236Sken xpt_done(ccb); 1927265236Sken return; 1928265236Sken } 1929265236Sken 1930265236Sken if ((sc->mpr_flags & MPR_FLAGS_SHUTDOWN) != 0) { 1931283990Sslm mpr_dprint(sc, MPR_INFO, "%s shutting down\n", __func__); 1932283990Sslm mprsas_set_ccbstatus(ccb, CAM_DEV_NOT_THERE); 1933265236Sken xpt_done(ccb); 1934265236Sken return; 1935265236Sken } 1936265236Sken 1937283990Sslm /* 1938283990Sslm * If target has a reset in progress, freeze the devq and return. The 1939283990Sslm * devq will be released when the TM reset is finished. 1940283990Sslm */ 1941283990Sslm if (targ->flags & MPRSAS_TARGET_INRESET) { 1942283990Sslm ccb->ccb_h.status = CAM_BUSY | CAM_DEV_QFRZN; 1943283990Sslm mpr_dprint(sc, MPR_INFO, "%s: Freezing devq for target ID %d\n", 1944283990Sslm __func__, targ->tid); 1945283990Sslm xpt_freeze_devq(ccb->ccb_h.path, 1); 1946283990Sslm xpt_done(ccb); 1947283990Sslm return; 1948283990Sslm } 1949283990Sslm 1950265236Sken cm = mpr_alloc_command(sc); 1951265236Sken if (cm == NULL || (sc->mpr_flags & MPR_FLAGS_DIAGRESET)) { 1952265236Sken if (cm != NULL) { 1953265236Sken mpr_free_command(sc, cm); 1954265236Sken } 1955265236Sken if ((sassc->flags & MPRSAS_QUEUE_FROZEN) == 0) { 1956265236Sken xpt_freeze_simq(sassc->sim, 1); 1957265236Sken sassc->flags |= MPRSAS_QUEUE_FROZEN; 1958265236Sken } 1959265236Sken ccb->ccb_h.status &= ~CAM_SIM_QUEUED; 1960265236Sken ccb->ccb_h.status |= CAM_REQUEUE_REQ; 1961265236Sken xpt_done(ccb); 1962265236Sken return; 1963265236Sken } 1964265236Sken 1965319436Sslm /* For NVME device's issue UNMAP command directly to NVME drives by 1966319436Sslm * constructing equivalent native NVMe DataSetManagement command. 1967319436Sslm */ 1968319436Sslm#if __FreeBSD_version >= 1100103 1969319436Sslm scsi_opcode = scsiio_cdb_ptr(csio)[0]; 1970319436Sslm#else 1971319436Sslm if (csio->ccb_h.flags & CAM_CDB_POINTER) 1972319436Sslm scsi_opcode = csio->cdb_io.cdb_ptr[0]; 1973319436Sslm else 1974319436Sslm scsi_opcode = csio->cdb_io.cdb_bytes[0]; 1975319436Sslm#endif 1976319436Sslm if (scsi_opcode == UNMAP && 1977319436Sslm targ->is_nvme && 1978319436Sslm (csio->ccb_h.flags & CAM_DATA_MASK) == CAM_DATA_VADDR) { 1979319436Sslm rc = mprsas_build_nvme_unmap(sc, cm, ccb, targ); 1980319436Sslm if (rc == 1) { /* return command to CAM with success status */ 1981319436Sslm mpr_free_command(sc, cm); 1982319436Sslm mprsas_set_ccbstatus(ccb, CAM_REQ_CMP); 1983319436Sslm xpt_done(ccb); 1984319436Sslm return; 1985319436Sslm } else if (!rc) /* Issued NVMe Encapsulated Request Message */ 1986319436Sslm return; 1987319436Sslm } 1988319436Sslm 1989265236Sken req = (MPI2_SCSI_IO_REQUEST *)cm->cm_req; 1990265236Sken bzero(req, sizeof(*req)); 1991265236Sken req->DevHandle = htole16(targ->handle); 1992265236Sken req->Function = MPI2_FUNCTION_SCSI_IO_REQUEST; 1993265236Sken req->MsgFlags = 0; 1994265236Sken req->SenseBufferLowAddress = htole32(cm->cm_sense_busaddr); 1995265236Sken req->SenseBufferLength = MPR_SENSE_LEN; 1996265236Sken req->SGLFlags = 0; 1997265236Sken req->ChainOffset = 0; 1998265236Sken req->SGLOffset0 = 24; /* 32bit word offset to the SGL */ 1999265236Sken req->SGLOffset1= 0; 2000265236Sken req->SGLOffset2= 0; 2001265236Sken req->SGLOffset3= 0; 2002265236Sken req->SkipCount = 0; 2003265236Sken req->DataLength = htole32(csio->dxfer_len); 2004265236Sken req->BidirectionalDataLength = 0; 2005265236Sken req->IoFlags = htole16(csio->cdb_len); 2006265236Sken req->EEDPFlags = 0; 2007265236Sken 2008265236Sken /* Note: BiDirectional transfers are not supported */ 2009265236Sken switch (csio->ccb_h.flags & CAM_DIR_MASK) { 2010265236Sken case CAM_DIR_IN: 2011265236Sken mpi_control = MPI2_SCSIIO_CONTROL_READ; 2012265236Sken cm->cm_flags |= MPR_CM_FLAGS_DATAIN; 2013265236Sken break; 2014265236Sken case CAM_DIR_OUT: 2015265236Sken mpi_control = MPI2_SCSIIO_CONTROL_WRITE; 2016265236Sken cm->cm_flags |= MPR_CM_FLAGS_DATAOUT; 2017265236Sken break; 2018265236Sken case CAM_DIR_NONE: 2019265236Sken default: 2020265236Sken mpi_control = MPI2_SCSIIO_CONTROL_NODATATRANSFER; 2021265236Sken break; 2022265236Sken } 2023265236Sken 2024265236Sken if (csio->cdb_len == 32) 2025265236Sken mpi_control |= 4 << MPI2_SCSIIO_CONTROL_ADDCDBLEN_SHIFT; 2026265236Sken /* 2027265236Sken * It looks like the hardware doesn't require an explicit tag 2028265236Sken * number for each transaction. SAM Task Management not supported 2029265236Sken * at the moment. 2030265236Sken */ 2031265236Sken switch (csio->tag_action) { 2032265236Sken case MSG_HEAD_OF_Q_TAG: 2033265236Sken mpi_control |= MPI2_SCSIIO_CONTROL_HEADOFQ; 2034265236Sken break; 2035265236Sken case MSG_ORDERED_Q_TAG: 2036265236Sken mpi_control |= MPI2_SCSIIO_CONTROL_ORDEREDQ; 2037265236Sken break; 2038265236Sken case MSG_ACA_TASK: 2039265236Sken mpi_control |= MPI2_SCSIIO_CONTROL_ACAQ; 2040265236Sken break; 2041265236Sken case CAM_TAG_ACTION_NONE: 2042265236Sken case MSG_SIMPLE_Q_TAG: 2043265236Sken default: 2044265236Sken mpi_control |= MPI2_SCSIIO_CONTROL_SIMPLEQ; 2045265236Sken break; 2046265236Sken } 2047265236Sken mpi_control |= sc->mapping_table[csio->ccb_h.target_id].TLR_bits; 2048265236Sken req->Control = htole32(mpi_control); 2049265236Sken 2050265236Sken if (MPR_SET_LUN(req->LUN, csio->ccb_h.target_lun) != 0) { 2051265236Sken mpr_free_command(sc, cm); 2052283990Sslm mprsas_set_ccbstatus(ccb, CAM_LUN_INVALID); 2053265236Sken xpt_done(ccb); 2054265236Sken return; 2055265236Sken } 2056265236Sken 2057265236Sken if (csio->ccb_h.flags & CAM_CDB_POINTER) 2058265236Sken bcopy(csio->cdb_io.cdb_ptr, &req->CDB.CDB32[0], csio->cdb_len); 2059313103Sasomers else { 2060313103Sasomers KASSERT(csio->cdb_len <= IOCDBLEN, 2061319436Sslm ("cdb_len %d is greater than IOCDBLEN but CAM_CDB_POINTER " 2062319436Sslm "is not set", csio->cdb_len)); 2063265236Sken bcopy(csio->cdb_io.cdb_bytes, &req->CDB.CDB32[0],csio->cdb_len); 2064313103Sasomers } 2065265236Sken req->IoFlags = htole16(csio->cdb_len); 2066265236Sken 2067265236Sken /* 2068265236Sken * Check if EEDP is supported and enabled. If it is then check if the 2069265236Sken * SCSI opcode could be using EEDP. If so, make sure the LUN exists and 2070265236Sken * is formatted for EEDP support. If all of this is true, set CDB up 2071265236Sken * for EEDP transfer. 2072265236Sken */ 2073265236Sken eedp_flags = op_code_prot[req->CDB.CDB32[0]]; 2074265236Sken if (sc->eedp_enabled && eedp_flags) { 2075265236Sken SLIST_FOREACH(lun, &targ->luns, lun_link) { 2076265236Sken if (lun->lun_id == csio->ccb_h.target_lun) { 2077265236Sken break; 2078265236Sken } 2079265236Sken } 2080265236Sken 2081265236Sken if ((lun != NULL) && (lun->eedp_formatted)) { 2082265236Sken req->EEDPBlockSize = htole16(lun->eedp_block_size); 2083265236Sken eedp_flags |= (MPI2_SCSIIO_EEDPFLAGS_INC_PRI_REFTAG | 2084265236Sken MPI2_SCSIIO_EEDPFLAGS_CHECK_REFTAG | 2085265236Sken MPI2_SCSIIO_EEDPFLAGS_CHECK_GUARD); 2086319436Sslm if (sc->mpr_flags & MPR_FLAGS_GEN35_IOC) { 2087319436Sslm eedp_flags |= 2088319436Sslm MPI25_SCSIIO_EEDPFLAGS_APPTAG_DISABLE_MODE; 2089319436Sslm } 2090265236Sken req->EEDPFlags = htole16(eedp_flags); 2091265236Sken 2092265236Sken /* 2093265236Sken * If CDB less than 32, fill in Primary Ref Tag with 2094265236Sken * low 4 bytes of LBA. If CDB is 32, tag stuff is 2095265236Sken * already there. Also, set protection bit. FreeBSD 2096265236Sken * currently does not support CDBs bigger than 16, but 2097265236Sken * the code doesn't hurt, and will be here for the 2098265236Sken * future. 2099265236Sken */ 2100265236Sken if (csio->cdb_len != 32) { 2101265236Sken lba_byte = (csio->cdb_len == 16) ? 6 : 2; 2102265236Sken ref_tag_addr = (uint8_t *)&req->CDB.EEDP32. 2103265236Sken PrimaryReferenceTag; 2104265236Sken for (i = 0; i < 4; i++) { 2105265236Sken *ref_tag_addr = 2106265236Sken req->CDB.CDB32[lba_byte + i]; 2107265236Sken ref_tag_addr++; 2108265236Sken } 2109265236Sken req->CDB.EEDP32.PrimaryReferenceTag = 2110265236Sken htole32(req-> 2111265236Sken CDB.EEDP32.PrimaryReferenceTag); 2112265236Sken req->CDB.EEDP32.PrimaryApplicationTagMask = 2113265236Sken 0xFFFF; 2114265236Sken req->CDB.CDB32[1] = (req->CDB.CDB32[1] & 0x1F) | 2115265236Sken 0x20; 2116265236Sken } else { 2117265236Sken eedp_flags |= 2118265236Sken MPI2_SCSIIO_EEDPFLAGS_INC_PRI_APPTAG; 2119265236Sken req->EEDPFlags = htole16(eedp_flags); 2120265236Sken req->CDB.CDB32[10] = (req->CDB.CDB32[10] & 2121265236Sken 0x1F) | 0x20; 2122265236Sken } 2123265236Sken } 2124265236Sken } 2125265236Sken 2126265236Sken cm->cm_length = csio->dxfer_len; 2127265236Sken if (cm->cm_length != 0) { 2128265236Sken cm->cm_data = ccb; 2129265236Sken cm->cm_flags |= MPR_CM_FLAGS_USE_CCB; 2130265236Sken } else { 2131265236Sken cm->cm_data = NULL; 2132265236Sken } 2133265236Sken cm->cm_sge = &req->SGL; 2134265236Sken cm->cm_sglsize = (32 - 24) * 4; 2135265236Sken cm->cm_complete = mprsas_scsiio_complete; 2136265236Sken cm->cm_complete_data = ccb; 2137265236Sken cm->cm_targ = targ; 2138265236Sken cm->cm_lun = csio->ccb_h.target_lun; 2139265236Sken cm->cm_ccb = ccb; 2140265236Sken /* 2141265236Sken * If using FP desc type, need to set a bit in IoFlags (SCSI IO is 0) 2142265236Sken * and set descriptor type. 2143265236Sken */ 2144265236Sken if (targ->scsi_req_desc_type == 2145265236Sken MPI25_REQ_DESCRIPT_FLAGS_FAST_PATH_SCSI_IO) { 2146265236Sken req->IoFlags |= MPI25_SCSIIO_IOFLAGS_FAST_PATH; 2147265236Sken cm->cm_desc.FastPathSCSIIO.RequestFlags = 2148265236Sken MPI25_REQ_DESCRIPT_FLAGS_FAST_PATH_SCSI_IO; 2149319436Sslm if (!sc->atomic_desc_capable) { 2150319436Sslm cm->cm_desc.FastPathSCSIIO.DevHandle = 2151319436Sslm htole16(targ->handle); 2152319436Sslm } 2153265236Sken } else { 2154265236Sken cm->cm_desc.SCSIIO.RequestFlags = 2155265236Sken MPI2_REQ_DESCRIPT_FLAGS_SCSI_IO; 2156319436Sslm if (!sc->atomic_desc_capable) 2157319436Sslm cm->cm_desc.SCSIIO.DevHandle = htole16(targ->handle); 2158265236Sken } 2159265236Sken 2160299962Sslm#if __FreeBSD_version >= 1000029 2161275982Ssmh callout_reset_sbt(&cm->cm_callout, SBT_1MS * ccb->ccb_h.timeout, 0, 2162283990Sslm mprsas_scsiio_timeout, cm, 0); 2163299962Sslm#else //__FreeBSD_version < 1000029 2164299962Sslm callout_reset(&cm->cm_callout, (ccb->ccb_h.timeout * hz) / 1000, 2165299962Sslm mprsas_scsiio_timeout, cm); 2166299962Sslm#endif //__FreeBSD_version >= 1000029 2167265236Sken 2168265236Sken targ->issued++; 2169265236Sken targ->outstanding++; 2170265236Sken TAILQ_INSERT_TAIL(&targ->commands, cm, cm_link); 2171265236Sken ccb->ccb_h.status |= CAM_SIM_QUEUED; 2172265236Sken 2173265236Sken mprsas_log_command(cm, MPR_XINFO, "%s cm %p ccb %p outstanding %u\n", 2174265236Sken __func__, cm, ccb, targ->outstanding); 2175265236Sken 2176265236Sken mpr_map_command(sc, cm); 2177265236Sken return; 2178265236Sken} 2179265236Sken 2180265236Skenstatic void 2181265236Skenmpr_response_code(struct mpr_softc *sc, u8 response_code) 2182265236Sken{ 2183265236Sken char *desc; 2184265236Sken 2185265236Sken switch (response_code) { 2186265236Sken case MPI2_SCSITASKMGMT_RSP_TM_COMPLETE: 2187265236Sken desc = "task management request completed"; 2188265236Sken break; 2189265236Sken case MPI2_SCSITASKMGMT_RSP_INVALID_FRAME: 2190265236Sken desc = "invalid frame"; 2191265236Sken break; 2192265236Sken case MPI2_SCSITASKMGMT_RSP_TM_NOT_SUPPORTED: 2193265236Sken desc = "task management request not supported"; 2194265236Sken break; 2195265236Sken case MPI2_SCSITASKMGMT_RSP_TM_FAILED: 2196265236Sken desc = "task management request failed"; 2197265236Sken break; 2198265236Sken case MPI2_SCSITASKMGMT_RSP_TM_SUCCEEDED: 2199265236Sken desc = "task management request succeeded"; 2200265236Sken break; 2201265236Sken case MPI2_SCSITASKMGMT_RSP_TM_INVALID_LUN: 2202265236Sken desc = "invalid lun"; 2203265236Sken break; 2204265236Sken case 0xA: 2205265236Sken desc = "overlapped tag attempted"; 2206265236Sken break; 2207265236Sken case MPI2_SCSITASKMGMT_RSP_IO_QUEUED_ON_IOC: 2208265236Sken desc = "task queued, however not sent to target"; 2209265236Sken break; 2210265236Sken default: 2211265236Sken desc = "unknown"; 2212265236Sken break; 2213265236Sken } 2214265236Sken mpr_dprint(sc, MPR_XINFO, "response_code(0x%01x): %s\n", response_code, 2215265236Sken desc); 2216265236Sken} 2217265236Sken 2218265236Sken/** 2219265236Sken * mpr_sc_failed_io_info - translated non-succesfull SCSI_IO request 2220265236Sken */ 2221265236Skenstatic void 2222265236Skenmpr_sc_failed_io_info(struct mpr_softc *sc, struct ccb_scsiio *csio, 2223265236Sken Mpi2SCSIIOReply_t *mpi_reply, struct mprsas_target *targ) 2224265236Sken{ 2225265236Sken u32 response_info; 2226265236Sken u8 *response_bytes; 2227265236Sken u16 ioc_status = le16toh(mpi_reply->IOCStatus) & 2228265236Sken MPI2_IOCSTATUS_MASK; 2229265236Sken u8 scsi_state = mpi_reply->SCSIState; 2230265236Sken u8 scsi_status = mpi_reply->SCSIStatus; 2231265236Sken char *desc_ioc_state = NULL; 2232265236Sken char *desc_scsi_status = NULL; 2233265236Sken char *desc_scsi_state = sc->tmp_string; 2234265236Sken u32 log_info = le32toh(mpi_reply->IOCLogInfo); 2235265236Sken 2236265236Sken if (log_info == 0x31170000) 2237265236Sken return; 2238265236Sken 2239265236Sken switch (ioc_status) { 2240265236Sken case MPI2_IOCSTATUS_SUCCESS: 2241265236Sken desc_ioc_state = "success"; 2242265236Sken break; 2243265236Sken case MPI2_IOCSTATUS_INVALID_FUNCTION: 2244265236Sken desc_ioc_state = "invalid function"; 2245265236Sken break; 2246265236Sken case MPI2_IOCSTATUS_SCSI_RECOVERED_ERROR: 2247265236Sken desc_ioc_state = "scsi recovered error"; 2248265236Sken break; 2249265236Sken case MPI2_IOCSTATUS_SCSI_INVALID_DEVHANDLE: 2250265236Sken desc_ioc_state = "scsi invalid dev handle"; 2251265236Sken break; 2252265236Sken case MPI2_IOCSTATUS_SCSI_DEVICE_NOT_THERE: 2253265236Sken desc_ioc_state = "scsi device not there"; 2254265236Sken break; 2255265236Sken case MPI2_IOCSTATUS_SCSI_DATA_OVERRUN: 2256265236Sken desc_ioc_state = "scsi data overrun"; 2257265236Sken break; 2258265236Sken case MPI2_IOCSTATUS_SCSI_DATA_UNDERRUN: 2259265236Sken desc_ioc_state = "scsi data underrun"; 2260265236Sken break; 2261265236Sken case MPI2_IOCSTATUS_SCSI_IO_DATA_ERROR: 2262265236Sken desc_ioc_state = "scsi io data error"; 2263265236Sken break; 2264265236Sken case MPI2_IOCSTATUS_SCSI_PROTOCOL_ERROR: 2265265236Sken desc_ioc_state = "scsi protocol error"; 2266265236Sken break; 2267265236Sken case MPI2_IOCSTATUS_SCSI_TASK_TERMINATED: 2268265236Sken desc_ioc_state = "scsi task terminated"; 2269265236Sken break; 2270265236Sken case MPI2_IOCSTATUS_SCSI_RESIDUAL_MISMATCH: 2271265236Sken desc_ioc_state = "scsi residual mismatch"; 2272265236Sken break; 2273265236Sken case MPI2_IOCSTATUS_SCSI_TASK_MGMT_FAILED: 2274265236Sken desc_ioc_state = "scsi task mgmt failed"; 2275265236Sken break; 2276265236Sken case MPI2_IOCSTATUS_SCSI_IOC_TERMINATED: 2277265236Sken desc_ioc_state = "scsi ioc terminated"; 2278265236Sken break; 2279265236Sken case MPI2_IOCSTATUS_SCSI_EXT_TERMINATED: 2280265236Sken desc_ioc_state = "scsi ext terminated"; 2281265236Sken break; 2282265236Sken case MPI2_IOCSTATUS_EEDP_GUARD_ERROR: 2283265236Sken desc_ioc_state = "eedp guard error"; 2284265236Sken break; 2285265236Sken case MPI2_IOCSTATUS_EEDP_REF_TAG_ERROR: 2286265236Sken desc_ioc_state = "eedp ref tag error"; 2287265236Sken break; 2288265236Sken case MPI2_IOCSTATUS_EEDP_APP_TAG_ERROR: 2289265236Sken desc_ioc_state = "eedp app tag error"; 2290265236Sken break; 2291299962Sslm case MPI2_IOCSTATUS_INSUFFICIENT_POWER: 2292299962Sslm desc_ioc_state = "insufficient power"; 2293299962Sslm break; 2294265236Sken default: 2295265236Sken desc_ioc_state = "unknown"; 2296265236Sken break; 2297265236Sken } 2298265236Sken 2299265236Sken switch (scsi_status) { 2300265236Sken case MPI2_SCSI_STATUS_GOOD: 2301265236Sken desc_scsi_status = "good"; 2302265236Sken break; 2303265236Sken case MPI2_SCSI_STATUS_CHECK_CONDITION: 2304265236Sken desc_scsi_status = "check condition"; 2305265236Sken break; 2306265236Sken case MPI2_SCSI_STATUS_CONDITION_MET: 2307265236Sken desc_scsi_status = "condition met"; 2308265236Sken break; 2309265236Sken case MPI2_SCSI_STATUS_BUSY: 2310265236Sken desc_scsi_status = "busy"; 2311265236Sken break; 2312265236Sken case MPI2_SCSI_STATUS_INTERMEDIATE: 2313265236Sken desc_scsi_status = "intermediate"; 2314265236Sken break; 2315265236Sken case MPI2_SCSI_STATUS_INTERMEDIATE_CONDMET: 2316265236Sken desc_scsi_status = "intermediate condmet"; 2317265236Sken break; 2318265236Sken case MPI2_SCSI_STATUS_RESERVATION_CONFLICT: 2319265236Sken desc_scsi_status = "reservation conflict"; 2320265236Sken break; 2321265236Sken case MPI2_SCSI_STATUS_COMMAND_TERMINATED: 2322265236Sken desc_scsi_status = "command terminated"; 2323265236Sken break; 2324265236Sken case MPI2_SCSI_STATUS_TASK_SET_FULL: 2325265236Sken desc_scsi_status = "task set full"; 2326265236Sken break; 2327265236Sken case MPI2_SCSI_STATUS_ACA_ACTIVE: 2328265236Sken desc_scsi_status = "aca active"; 2329265236Sken break; 2330265236Sken case MPI2_SCSI_STATUS_TASK_ABORTED: 2331265236Sken desc_scsi_status = "task aborted"; 2332265236Sken break; 2333265236Sken default: 2334265236Sken desc_scsi_status = "unknown"; 2335265236Sken break; 2336265236Sken } 2337265236Sken 2338265236Sken desc_scsi_state[0] = '\0'; 2339265236Sken if (!scsi_state) 2340265236Sken desc_scsi_state = " "; 2341265236Sken if (scsi_state & MPI2_SCSI_STATE_RESPONSE_INFO_VALID) 2342265236Sken strcat(desc_scsi_state, "response info "); 2343265236Sken if (scsi_state & MPI2_SCSI_STATE_TERMINATED) 2344265236Sken strcat(desc_scsi_state, "state terminated "); 2345265236Sken if (scsi_state & MPI2_SCSI_STATE_NO_SCSI_STATUS) 2346265236Sken strcat(desc_scsi_state, "no status "); 2347265236Sken if (scsi_state & MPI2_SCSI_STATE_AUTOSENSE_FAILED) 2348265236Sken strcat(desc_scsi_state, "autosense failed "); 2349265236Sken if (scsi_state & MPI2_SCSI_STATE_AUTOSENSE_VALID) 2350265236Sken strcat(desc_scsi_state, "autosense valid "); 2351265236Sken 2352265236Sken mpr_dprint(sc, MPR_XINFO, "\thandle(0x%04x), ioc_status(%s)(0x%04x)\n", 2353265236Sken le16toh(mpi_reply->DevHandle), desc_ioc_state, ioc_status); 2354265236Sken if (targ->encl_level_valid) { 2355265236Sken mpr_dprint(sc, MPR_XINFO, "At enclosure level %d, slot %d, " 2356265236Sken "connector name (%4s)\n", targ->encl_level, targ->encl_slot, 2357265236Sken targ->connector_name); 2358265236Sken } 2359265236Sken /* We can add more detail about underflow data here 2360265236Sken * TO-DO 2361265236Sken * */ 2362265236Sken mpr_dprint(sc, MPR_XINFO, "\tscsi_status(%s)(0x%02x), " 2363265236Sken "scsi_state(%s)(0x%02x)\n", desc_scsi_status, scsi_status, 2364265236Sken desc_scsi_state, scsi_state); 2365265236Sken 2366265236Sken if (sc->mpr_debug & MPR_XINFO && 2367283990Sslm scsi_state & MPI2_SCSI_STATE_AUTOSENSE_VALID) { 2368265236Sken mpr_dprint(sc, MPR_XINFO, "-> Sense Buffer Data : Start :\n"); 2369265236Sken scsi_sense_print(csio); 2370265236Sken mpr_dprint(sc, MPR_XINFO, "-> Sense Buffer Data : End :\n"); 2371265236Sken } 2372265236Sken 2373265236Sken if (scsi_state & MPI2_SCSI_STATE_RESPONSE_INFO_VALID) { 2374265236Sken response_info = le32toh(mpi_reply->ResponseInfo); 2375265236Sken response_bytes = (u8 *)&response_info; 2376265236Sken mpr_response_code(sc,response_bytes[0]); 2377265236Sken } 2378265236Sken} 2379265236Sken 2380319436Sslm/** mprsas_nvme_trans_status_code 2381319436Sslm * 2382319436Sslm * Convert Native NVMe command error status to 2383319436Sslm * equivalent SCSI error status. 2384319436Sslm * 2385319436Sslm * Returns appropriate scsi_status 2386319436Sslm */ 2387319436Sslmstatic u8 2388319436Sslmmprsas_nvme_trans_status_code(struct nvme_status nvme_status, 2389319436Sslm struct mpr_command *cm) 2390319436Sslm{ 2391319436Sslm u8 status = MPI2_SCSI_STATUS_GOOD; 2392319436Sslm int skey, asc, ascq; 2393319436Sslm union ccb *ccb = cm->cm_complete_data; 2394319436Sslm int returned_sense_len; 2395319436Sslm 2396319436Sslm status = MPI2_SCSI_STATUS_CHECK_CONDITION; 2397319436Sslm skey = SSD_KEY_ILLEGAL_REQUEST; 2398319436Sslm asc = SCSI_ASC_NO_SENSE; 2399319436Sslm ascq = SCSI_ASCQ_CAUSE_NOT_REPORTABLE; 2400319436Sslm 2401319436Sslm switch (nvme_status.sct) { 2402319436Sslm case NVME_SCT_GENERIC: 2403319436Sslm switch (nvme_status.sc) { 2404319436Sslm case NVME_SC_SUCCESS: 2405319436Sslm status = MPI2_SCSI_STATUS_GOOD; 2406319436Sslm skey = SSD_KEY_NO_SENSE; 2407319436Sslm asc = SCSI_ASC_NO_SENSE; 2408319436Sslm ascq = SCSI_ASCQ_CAUSE_NOT_REPORTABLE; 2409319436Sslm break; 2410319436Sslm case NVME_SC_INVALID_OPCODE: 2411319436Sslm status = MPI2_SCSI_STATUS_CHECK_CONDITION; 2412319436Sslm skey = SSD_KEY_ILLEGAL_REQUEST; 2413319436Sslm asc = SCSI_ASC_ILLEGAL_COMMAND; 2414319436Sslm ascq = SCSI_ASCQ_CAUSE_NOT_REPORTABLE; 2415319436Sslm break; 2416319436Sslm case NVME_SC_INVALID_FIELD: 2417319436Sslm status = MPI2_SCSI_STATUS_CHECK_CONDITION; 2418319436Sslm skey = SSD_KEY_ILLEGAL_REQUEST; 2419319436Sslm asc = SCSI_ASC_INVALID_CDB; 2420319436Sslm ascq = SCSI_ASCQ_CAUSE_NOT_REPORTABLE; 2421319436Sslm break; 2422319436Sslm case NVME_SC_DATA_TRANSFER_ERROR: 2423319436Sslm status = MPI2_SCSI_STATUS_CHECK_CONDITION; 2424319436Sslm skey = SSD_KEY_MEDIUM_ERROR; 2425319436Sslm asc = SCSI_ASC_NO_SENSE; 2426319436Sslm ascq = SCSI_ASCQ_CAUSE_NOT_REPORTABLE; 2427319436Sslm break; 2428319436Sslm case NVME_SC_ABORTED_POWER_LOSS: 2429319436Sslm status = MPI2_SCSI_STATUS_TASK_ABORTED; 2430319436Sslm skey = SSD_KEY_ABORTED_COMMAND; 2431319436Sslm asc = SCSI_ASC_WARNING; 2432319436Sslm ascq = SCSI_ASCQ_POWER_LOSS_EXPECTED; 2433319436Sslm break; 2434319436Sslm case NVME_SC_INTERNAL_DEVICE_ERROR: 2435319436Sslm status = MPI2_SCSI_STATUS_CHECK_CONDITION; 2436319436Sslm skey = SSD_KEY_HARDWARE_ERROR; 2437319436Sslm asc = SCSI_ASC_INTERNAL_TARGET_FAILURE; 2438319436Sslm ascq = SCSI_ASCQ_CAUSE_NOT_REPORTABLE; 2439319436Sslm break; 2440319436Sslm case NVME_SC_ABORTED_BY_REQUEST: 2441319436Sslm case NVME_SC_ABORTED_SQ_DELETION: 2442319436Sslm case NVME_SC_ABORTED_FAILED_FUSED: 2443319436Sslm case NVME_SC_ABORTED_MISSING_FUSED: 2444319436Sslm status = MPI2_SCSI_STATUS_TASK_ABORTED; 2445319436Sslm skey = SSD_KEY_ABORTED_COMMAND; 2446319436Sslm asc = SCSI_ASC_NO_SENSE; 2447319436Sslm ascq = SCSI_ASCQ_CAUSE_NOT_REPORTABLE; 2448319436Sslm break; 2449319436Sslm case NVME_SC_INVALID_NAMESPACE_OR_FORMAT: 2450319436Sslm status = MPI2_SCSI_STATUS_CHECK_CONDITION; 2451319436Sslm skey = SSD_KEY_ILLEGAL_REQUEST; 2452319436Sslm asc = SCSI_ASC_ACCESS_DENIED_INVALID_LUN_ID; 2453319436Sslm ascq = SCSI_ASCQ_INVALID_LUN_ID; 2454319436Sslm break; 2455319436Sslm case NVME_SC_LBA_OUT_OF_RANGE: 2456319436Sslm status = MPI2_SCSI_STATUS_CHECK_CONDITION; 2457319436Sslm skey = SSD_KEY_ILLEGAL_REQUEST; 2458319436Sslm asc = SCSI_ASC_ILLEGAL_BLOCK; 2459319436Sslm ascq = SCSI_ASCQ_CAUSE_NOT_REPORTABLE; 2460319436Sslm break; 2461319436Sslm case NVME_SC_CAPACITY_EXCEEDED: 2462319436Sslm status = MPI2_SCSI_STATUS_CHECK_CONDITION; 2463319436Sslm skey = SSD_KEY_MEDIUM_ERROR; 2464319436Sslm asc = SCSI_ASC_NO_SENSE; 2465319436Sslm ascq = SCSI_ASCQ_CAUSE_NOT_REPORTABLE; 2466319436Sslm break; 2467319436Sslm case NVME_SC_NAMESPACE_NOT_READY: 2468319436Sslm status = MPI2_SCSI_STATUS_CHECK_CONDITION; 2469319436Sslm skey = SSD_KEY_NOT_READY; 2470319436Sslm asc = SCSI_ASC_LUN_NOT_READY; 2471319436Sslm ascq = SCSI_ASCQ_CAUSE_NOT_REPORTABLE; 2472319436Sslm break; 2473319436Sslm } 2474319436Sslm break; 2475319436Sslm case NVME_SCT_COMMAND_SPECIFIC: 2476319436Sslm switch (nvme_status.sc) { 2477319436Sslm case NVME_SC_INVALID_FORMAT: 2478319436Sslm status = MPI2_SCSI_STATUS_CHECK_CONDITION; 2479319436Sslm skey = SSD_KEY_ILLEGAL_REQUEST; 2480319436Sslm asc = SCSI_ASC_FORMAT_COMMAND_FAILED; 2481319436Sslm ascq = SCSI_ASCQ_FORMAT_COMMAND_FAILED; 2482319436Sslm break; 2483319436Sslm case NVME_SC_CONFLICTING_ATTRIBUTES: 2484319436Sslm status = MPI2_SCSI_STATUS_CHECK_CONDITION; 2485319436Sslm skey = SSD_KEY_ILLEGAL_REQUEST; 2486319436Sslm asc = SCSI_ASC_INVALID_CDB; 2487319436Sslm ascq = SCSI_ASCQ_CAUSE_NOT_REPORTABLE; 2488319436Sslm break; 2489319436Sslm } 2490319436Sslm break; 2491319436Sslm case NVME_SCT_MEDIA_ERROR: 2492319436Sslm switch (nvme_status.sc) { 2493319436Sslm case NVME_SC_WRITE_FAULTS: 2494319436Sslm status = MPI2_SCSI_STATUS_CHECK_CONDITION; 2495319436Sslm skey = SSD_KEY_MEDIUM_ERROR; 2496319436Sslm asc = SCSI_ASC_PERIPHERAL_DEV_WRITE_FAULT; 2497319436Sslm ascq = SCSI_ASCQ_CAUSE_NOT_REPORTABLE; 2498319436Sslm break; 2499319436Sslm case NVME_SC_UNRECOVERED_READ_ERROR: 2500319436Sslm status = MPI2_SCSI_STATUS_CHECK_CONDITION; 2501319436Sslm skey = SSD_KEY_MEDIUM_ERROR; 2502319436Sslm asc = SCSI_ASC_UNRECOVERED_READ_ERROR; 2503319436Sslm ascq = SCSI_ASCQ_CAUSE_NOT_REPORTABLE; 2504319436Sslm break; 2505319436Sslm case NVME_SC_GUARD_CHECK_ERROR: 2506319436Sslm status = MPI2_SCSI_STATUS_CHECK_CONDITION; 2507319436Sslm skey = SSD_KEY_MEDIUM_ERROR; 2508319436Sslm asc = SCSI_ASC_LOG_BLOCK_GUARD_CHECK_FAILED; 2509319436Sslm ascq = SCSI_ASCQ_LOG_BLOCK_GUARD_CHECK_FAILED; 2510319436Sslm break; 2511319436Sslm case NVME_SC_APPLICATION_TAG_CHECK_ERROR: 2512319436Sslm status = MPI2_SCSI_STATUS_CHECK_CONDITION; 2513319436Sslm skey = SSD_KEY_MEDIUM_ERROR; 2514319436Sslm asc = SCSI_ASC_LOG_BLOCK_APPTAG_CHECK_FAILED; 2515319436Sslm ascq = SCSI_ASCQ_LOG_BLOCK_APPTAG_CHECK_FAILED; 2516319436Sslm break; 2517319436Sslm case NVME_SC_REFERENCE_TAG_CHECK_ERROR: 2518319436Sslm status = MPI2_SCSI_STATUS_CHECK_CONDITION; 2519319436Sslm skey = SSD_KEY_MEDIUM_ERROR; 2520319436Sslm asc = SCSI_ASC_LOG_BLOCK_REFTAG_CHECK_FAILED; 2521319436Sslm ascq = SCSI_ASCQ_LOG_BLOCK_REFTAG_CHECK_FAILED; 2522319436Sslm break; 2523319436Sslm case NVME_SC_COMPARE_FAILURE: 2524319436Sslm status = MPI2_SCSI_STATUS_CHECK_CONDITION; 2525319436Sslm skey = SSD_KEY_MISCOMPARE; 2526319436Sslm asc = SCSI_ASC_MISCOMPARE_DURING_VERIFY; 2527319436Sslm ascq = SCSI_ASCQ_CAUSE_NOT_REPORTABLE; 2528319436Sslm break; 2529319436Sslm case NVME_SC_ACCESS_DENIED: 2530319436Sslm status = MPI2_SCSI_STATUS_CHECK_CONDITION; 2531319436Sslm skey = SSD_KEY_ILLEGAL_REQUEST; 2532319436Sslm asc = SCSI_ASC_ACCESS_DENIED_INVALID_LUN_ID; 2533319436Sslm ascq = SCSI_ASCQ_INVALID_LUN_ID; 2534319436Sslm break; 2535319436Sslm } 2536319436Sslm break; 2537319436Sslm } 2538319436Sslm 2539319436Sslm returned_sense_len = sizeof(struct scsi_sense_data); 2540319436Sslm if (returned_sense_len < ccb->csio.sense_len) 2541319436Sslm ccb->csio.sense_resid = ccb->csio.sense_len - 2542319436Sslm returned_sense_len; 2543319436Sslm else 2544319436Sslm ccb->csio.sense_resid = 0; 2545319436Sslm 2546319436Sslm scsi_set_sense_data(&ccb->csio.sense_data, SSD_TYPE_FIXED, 2547319436Sslm 1, skey, asc, ascq, SSD_ELEM_NONE); 2548319436Sslm ccb->ccb_h.status |= CAM_AUTOSNS_VALID; 2549319436Sslm 2550319436Sslm return status; 2551319436Sslm} 2552319436Sslm 2553319436Sslm/** mprsas_complete_nvme_unmap 2554319436Sslm * 2555319436Sslm * Complete native NVMe command issued using NVMe Encapsulated 2556319436Sslm * Request Message. 2557319436Sslm */ 2558319436Sslmstatic u8 2559319436Sslmmprsas_complete_nvme_unmap(struct mpr_softc *sc, struct mpr_command *cm) 2560319436Sslm{ 2561319436Sslm Mpi26NVMeEncapsulatedErrorReply_t *mpi_reply; 2562319436Sslm struct nvme_completion *nvme_completion = NULL; 2563319436Sslm u8 scsi_status = MPI2_SCSI_STATUS_GOOD; 2564319436Sslm 2565319436Sslm mpi_reply =(Mpi26NVMeEncapsulatedErrorReply_t *)cm->cm_reply; 2566319436Sslm if (le16toh(mpi_reply->ErrorResponseCount)){ 2567319436Sslm nvme_completion = (struct nvme_completion *)cm->cm_sense; 2568319436Sslm scsi_status = mprsas_nvme_trans_status_code( 2569319436Sslm nvme_completion->status, cm); 2570319436Sslm } 2571319436Sslm return scsi_status; 2572319436Sslm} 2573319436Sslm 2574265236Skenstatic void 2575265236Skenmprsas_scsiio_complete(struct mpr_softc *sc, struct mpr_command *cm) 2576265236Sken{ 2577265236Sken MPI2_SCSI_IO_REPLY *rep; 2578265236Sken union ccb *ccb; 2579265236Sken struct ccb_scsiio *csio; 2580265236Sken struct mprsas_softc *sassc; 2581265236Sken struct scsi_vpd_supported_page_list *vpd_list = NULL; 2582319436Sslm u8 *TLR_bits, TLR_on, *scsi_cdb; 2583265236Sken int dir = 0, i; 2584265236Sken u16 alloc_len; 2585283990Sslm struct mprsas_target *target; 2586283990Sslm target_id_t target_id; 2587265236Sken 2588265236Sken MPR_FUNCTRACE(sc); 2589265236Sken mpr_dprint(sc, MPR_TRACE, 2590265236Sken "cm %p SMID %u ccb %p reply %p outstanding %u\n", cm, 2591265236Sken cm->cm_desc.Default.SMID, cm->cm_ccb, cm->cm_reply, 2592265236Sken cm->cm_targ->outstanding); 2593265236Sken 2594265236Sken callout_stop(&cm->cm_callout); 2595265236Sken mtx_assert(&sc->mpr_mtx, MA_OWNED); 2596265236Sken 2597265236Sken sassc = sc->sassc; 2598265236Sken ccb = cm->cm_complete_data; 2599265236Sken csio = &ccb->csio; 2600283990Sslm target_id = csio->ccb_h.target_id; 2601265236Sken rep = (MPI2_SCSI_IO_REPLY *)cm->cm_reply; 2602265236Sken /* 2603265236Sken * XXX KDM if the chain allocation fails, does it matter if we do 2604265236Sken * the sync and unload here? It is simpler to do it in every case, 2605265236Sken * assuming it doesn't cause problems. 2606265236Sken */ 2607265236Sken if (cm->cm_data != NULL) { 2608265236Sken if (cm->cm_flags & MPR_CM_FLAGS_DATAIN) 2609265236Sken dir = BUS_DMASYNC_POSTREAD; 2610265236Sken else if (cm->cm_flags & MPR_CM_FLAGS_DATAOUT) 2611265236Sken dir = BUS_DMASYNC_POSTWRITE; 2612265236Sken bus_dmamap_sync(sc->buffer_dmat, cm->cm_dmamap, dir); 2613265236Sken bus_dmamap_unload(sc->buffer_dmat, cm->cm_dmamap); 2614265236Sken } 2615265236Sken 2616265236Sken cm->cm_targ->completed++; 2617265236Sken cm->cm_targ->outstanding--; 2618265236Sken TAILQ_REMOVE(&cm->cm_targ->commands, cm, cm_link); 2619265236Sken ccb->ccb_h.status &= ~(CAM_STATUS_MASK | CAM_SIM_QUEUED); 2620265236Sken 2621265236Sken if (cm->cm_state == MPR_CM_STATE_TIMEDOUT) { 2622265236Sken TAILQ_REMOVE(&cm->cm_targ->timedout_commands, cm, cm_recovery); 2623265236Sken if (cm->cm_reply != NULL) 2624265236Sken mprsas_log_command(cm, MPR_RECOVERY, 2625265236Sken "completed timedout cm %p ccb %p during recovery " 2626265236Sken "ioc %x scsi %x state %x xfer %u\n", cm, cm->cm_ccb, 2627265236Sken le16toh(rep->IOCStatus), rep->SCSIStatus, 2628265236Sken rep->SCSIState, le32toh(rep->TransferCount)); 2629265236Sken else 2630265236Sken mprsas_log_command(cm, MPR_RECOVERY, 2631265236Sken "completed timedout cm %p ccb %p during recovery\n", 2632265236Sken cm, cm->cm_ccb); 2633265236Sken } else if (cm->cm_targ->tm != NULL) { 2634265236Sken if (cm->cm_reply != NULL) 2635265236Sken mprsas_log_command(cm, MPR_RECOVERY, 2636265236Sken "completed cm %p ccb %p during recovery " 2637265236Sken "ioc %x scsi %x state %x xfer %u\n", 2638265236Sken cm, cm->cm_ccb, le16toh(rep->IOCStatus), 2639265236Sken rep->SCSIStatus, rep->SCSIState, 2640265236Sken le32toh(rep->TransferCount)); 2641265236Sken else 2642265236Sken mprsas_log_command(cm, MPR_RECOVERY, 2643265236Sken "completed cm %p ccb %p during recovery\n", 2644265236Sken cm, cm->cm_ccb); 2645265236Sken } else if ((sc->mpr_flags & MPR_FLAGS_DIAGRESET) != 0) { 2646265236Sken mprsas_log_command(cm, MPR_RECOVERY, 2647265236Sken "reset completed cm %p ccb %p\n", cm, cm->cm_ccb); 2648265236Sken } 2649265236Sken 2650265236Sken if ((cm->cm_flags & MPR_CM_FLAGS_ERROR_MASK) != 0) { 2651265236Sken /* 2652265236Sken * We ran into an error after we tried to map the command, 2653265236Sken * so we're getting a callback without queueing the command 2654265236Sken * to the hardware. So we set the status here, and it will 2655265236Sken * be retained below. We'll go through the "fast path", 2656265236Sken * because there can be no reply when we haven't actually 2657265236Sken * gone out to the hardware. 2658265236Sken */ 2659283990Sslm mprsas_set_ccbstatus(ccb, CAM_REQUEUE_REQ); 2660265236Sken 2661265236Sken /* 2662265236Sken * Currently the only error included in the mask is 2663265236Sken * MPR_CM_FLAGS_CHAIN_FAILED, which means we're out of 2664265236Sken * chain frames. We need to freeze the queue until we get 2665265236Sken * a command that completed without this error, which will 2666265236Sken * hopefully have some chain frames attached that we can 2667265236Sken * use. If we wanted to get smarter about it, we would 2668265236Sken * only unfreeze the queue in this condition when we're 2669265236Sken * sure that we're getting some chain frames back. That's 2670265236Sken * probably unnecessary. 2671265236Sken */ 2672265236Sken if ((sassc->flags & MPRSAS_QUEUE_FROZEN) == 0) { 2673265236Sken xpt_freeze_simq(sassc->sim, 1); 2674265236Sken sassc->flags |= MPRSAS_QUEUE_FROZEN; 2675322661Sken mpr_dprint(sc, MPR_XINFO, "Error sending command, " 2676283990Sslm "freezing SIM queue\n"); 2677265236Sken } 2678265236Sken } 2679265236Sken 2680265236Sken /* 2681319436Sslm * Point to the SCSI CDB, which is dependent on the CAM_CDB_POINTER 2682319436Sslm * flag, and use it in a few places in the rest of this function for 2683319436Sslm * convenience. Use the macro if available. 2684319436Sslm */ 2685319436Sslm#if __FreeBSD_version >= 1100103 2686319436Sslm scsi_cdb = scsiio_cdb_ptr(csio); 2687319436Sslm#else 2688319436Sslm if (csio->ccb_h.flags & CAM_CDB_POINTER) 2689319436Sslm scsi_cdb = csio->cdb_io.cdb_ptr; 2690319436Sslm else 2691319436Sslm scsi_cdb = csio->cdb_io.cdb_bytes; 2692319436Sslm#endif 2693319436Sslm 2694319436Sslm /* 2695265236Sken * If this is a Start Stop Unit command and it was issued by the driver 2696265236Sken * during shutdown, decrement the refcount to account for all of the 2697265236Sken * commands that were sent. All SSU commands should be completed before 2698265236Sken * shutdown completes, meaning SSU_refcount will be 0 after SSU_started 2699265236Sken * is TRUE. 2700283990Sslm */ 2701319436Sslm if (sc->SSU_started && (scsi_cdb[0] == START_STOP_UNIT)) { 2702265236Sken mpr_dprint(sc, MPR_INFO, "Decrementing SSU count.\n"); 2703265236Sken sc->SSU_refcount--; 2704265236Sken } 2705265236Sken 2706265236Sken /* Take the fast path to completion */ 2707265236Sken if (cm->cm_reply == NULL) { 2708283990Sslm if (mprsas_get_ccbstatus(ccb) == CAM_REQ_INPROG) { 2709265236Sken if ((sc->mpr_flags & MPR_FLAGS_DIAGRESET) != 0) 2710283990Sslm mprsas_set_ccbstatus(ccb, CAM_SCSI_BUS_RESET); 2711265236Sken else { 2712283990Sslm mprsas_set_ccbstatus(ccb, CAM_REQ_CMP); 2713283990Sslm csio->scsi_status = SCSI_STATUS_OK; 2714265236Sken } 2715265236Sken if (sassc->flags & MPRSAS_QUEUE_FROZEN) { 2716265236Sken ccb->ccb_h.status |= CAM_RELEASE_SIMQ; 2717265236Sken sassc->flags &= ~MPRSAS_QUEUE_FROZEN; 2718265236Sken mpr_dprint(sc, MPR_XINFO, 2719265236Sken "Unfreezing SIM queue\n"); 2720265236Sken } 2721265236Sken } 2722265236Sken 2723265236Sken /* 2724265236Sken * There are two scenarios where the status won't be 2725265236Sken * CAM_REQ_CMP. The first is if MPR_CM_FLAGS_ERROR_MASK is 2726265236Sken * set, the second is in the MPR_FLAGS_DIAGRESET above. 2727265236Sken */ 2728283990Sslm if (mprsas_get_ccbstatus(ccb) != CAM_REQ_CMP) { 2729265236Sken /* 2730265236Sken * Freeze the dev queue so that commands are 2731283990Sslm * executed in the correct order after error 2732265236Sken * recovery. 2733265236Sken */ 2734265236Sken ccb->ccb_h.status |= CAM_DEV_QFRZN; 2735265236Sken xpt_freeze_devq(ccb->ccb_h.path, /*count*/ 1); 2736265236Sken } 2737265236Sken mpr_free_command(sc, cm); 2738265236Sken xpt_done(ccb); 2739265236Sken return; 2740265236Sken } 2741265236Sken 2742319436Sslm target = &sassc->targets[target_id]; 2743319436Sslm if (scsi_cdb[0] == UNMAP && 2744319436Sslm target->is_nvme && 2745319436Sslm (csio->ccb_h.flags & CAM_DATA_MASK) == CAM_DATA_VADDR) { 2746319436Sslm rep->SCSIStatus = mprsas_complete_nvme_unmap(sc, cm); 2747319436Sslm csio->scsi_status = rep->SCSIStatus; 2748319436Sslm } 2749319436Sslm 2750265236Sken mprsas_log_command(cm, MPR_XINFO, 2751265236Sken "ioc %x scsi %x state %x xfer %u\n", 2752265236Sken le16toh(rep->IOCStatus), rep->SCSIStatus, rep->SCSIState, 2753265236Sken le32toh(rep->TransferCount)); 2754265236Sken 2755265236Sken switch (le16toh(rep->IOCStatus) & MPI2_IOCSTATUS_MASK) { 2756265236Sken case MPI2_IOCSTATUS_SCSI_DATA_UNDERRUN: 2757265236Sken csio->resid = cm->cm_length - le32toh(rep->TransferCount); 2758265236Sken /* FALLTHROUGH */ 2759265236Sken case MPI2_IOCSTATUS_SUCCESS: 2760265236Sken case MPI2_IOCSTATUS_SCSI_RECOVERED_ERROR: 2761265236Sken if ((le16toh(rep->IOCStatus) & MPI2_IOCSTATUS_MASK) == 2762265236Sken MPI2_IOCSTATUS_SCSI_RECOVERED_ERROR) 2763265236Sken mprsas_log_command(cm, MPR_XINFO, "recovered error\n"); 2764265236Sken 2765265236Sken /* Completion failed at the transport level. */ 2766265236Sken if (rep->SCSIState & (MPI2_SCSI_STATE_NO_SCSI_STATUS | 2767265236Sken MPI2_SCSI_STATE_TERMINATED)) { 2768283990Sslm mprsas_set_ccbstatus(ccb, CAM_REQ_CMP_ERR); 2769265236Sken break; 2770265236Sken } 2771265236Sken 2772265236Sken /* In a modern packetized environment, an autosense failure 2773265236Sken * implies that there's not much else that can be done to 2774265236Sken * recover the command. 2775265236Sken */ 2776265236Sken if (rep->SCSIState & MPI2_SCSI_STATE_AUTOSENSE_FAILED) { 2777283990Sslm mprsas_set_ccbstatus(ccb, CAM_AUTOSENSE_FAIL); 2778265236Sken break; 2779265236Sken } 2780265236Sken 2781265236Sken /* 2782265236Sken * CAM doesn't care about SAS Response Info data, but if this is 2783265236Sken * the state check if TLR should be done. If not, clear the 2784265236Sken * TLR_bits for the target. 2785265236Sken */ 2786265236Sken if ((rep->SCSIState & MPI2_SCSI_STATE_RESPONSE_INFO_VALID) && 2787265236Sken ((le32toh(rep->ResponseInfo) & MPI2_SCSI_RI_MASK_REASONCODE) 2788265236Sken == MPR_SCSI_RI_INVALID_FRAME)) { 2789283990Sslm sc->mapping_table[target_id].TLR_bits = 2790265236Sken (u8)MPI2_SCSIIO_CONTROL_NO_TLR; 2791265236Sken } 2792265236Sken 2793265236Sken /* 2794265236Sken * Intentionally override the normal SCSI status reporting 2795265236Sken * for these two cases. These are likely to happen in a 2796265236Sken * multi-initiator environment, and we want to make sure that 2797265236Sken * CAM retries these commands rather than fail them. 2798265236Sken */ 2799265236Sken if ((rep->SCSIStatus == MPI2_SCSI_STATUS_COMMAND_TERMINATED) || 2800265236Sken (rep->SCSIStatus == MPI2_SCSI_STATUS_TASK_ABORTED)) { 2801283990Sslm mprsas_set_ccbstatus(ccb, CAM_REQ_ABORTED); 2802265236Sken break; 2803265236Sken } 2804265236Sken 2805265236Sken /* Handle normal status and sense */ 2806265236Sken csio->scsi_status = rep->SCSIStatus; 2807265236Sken if (rep->SCSIStatus == MPI2_SCSI_STATUS_GOOD) 2808283990Sslm mprsas_set_ccbstatus(ccb, CAM_REQ_CMP); 2809265236Sken else 2810283990Sslm mprsas_set_ccbstatus(ccb, CAM_SCSI_STATUS_ERROR); 2811265236Sken 2812265236Sken if (rep->SCSIState & MPI2_SCSI_STATE_AUTOSENSE_VALID) { 2813265236Sken int sense_len, returned_sense_len; 2814265236Sken 2815265236Sken returned_sense_len = min(le32toh(rep->SenseCount), 2816265236Sken sizeof(struct scsi_sense_data)); 2817265236Sken if (returned_sense_len < csio->sense_len) 2818265236Sken csio->sense_resid = csio->sense_len - 2819265236Sken returned_sense_len; 2820265236Sken else 2821265236Sken csio->sense_resid = 0; 2822265236Sken 2823265236Sken sense_len = min(returned_sense_len, 2824265236Sken csio->sense_len - csio->sense_resid); 2825265236Sken bzero(&csio->sense_data, sizeof(csio->sense_data)); 2826265236Sken bcopy(cm->cm_sense, &csio->sense_data, sense_len); 2827265236Sken ccb->ccb_h.status |= CAM_AUTOSNS_VALID; 2828265236Sken } 2829265236Sken 2830265236Sken /* 2831265236Sken * Check if this is an INQUIRY command. If it's a VPD inquiry, 2832265236Sken * and it's page code 0 (Supported Page List), and there is 2833265236Sken * inquiry data, and this is for a sequential access device, and 2834265236Sken * the device is an SSP target, and TLR is supported by the 2835265236Sken * controller, turn the TLR_bits value ON if page 0x90 is 2836265236Sken * supported. 2837265236Sken */ 2838319436Sslm if ((scsi_cdb[0] == INQUIRY) && 2839319436Sslm (scsi_cdb[1] & SI_EVPD) && 2840319436Sslm (scsi_cdb[2] == SVPD_SUPPORTED_PAGE_LIST) && 2841265236Sken ((csio->ccb_h.flags & CAM_DATA_MASK) == CAM_DATA_VADDR) && 2842266548Sken (csio->data_ptr != NULL) && 2843266548Sken ((csio->data_ptr[0] & 0x1f) == T_SEQUENTIAL) && 2844266548Sken (sc->control_TLR) && 2845283990Sslm (sc->mapping_table[target_id].device_info & 2846265236Sken MPI2_SAS_DEVICE_INFO_SSP_TARGET)) { 2847265236Sken vpd_list = (struct scsi_vpd_supported_page_list *) 2848265236Sken csio->data_ptr; 2849283990Sslm TLR_bits = &sc->mapping_table[target_id].TLR_bits; 2850265236Sken *TLR_bits = (u8)MPI2_SCSIIO_CONTROL_NO_TLR; 2851265236Sken TLR_on = (u8)MPI2_SCSIIO_CONTROL_TLR_ON; 2852319436Sslm alloc_len = ((u16)scsi_cdb[3] << 8) + scsi_cdb[4]; 2853266548Sken alloc_len -= csio->resid; 2854265236Sken for (i = 0; i < MIN(vpd_list->length, alloc_len); i++) { 2855265236Sken if (vpd_list->list[i] == 0x90) { 2856265236Sken *TLR_bits = TLR_on; 2857265236Sken break; 2858265236Sken } 2859265236Sken } 2860265236Sken } 2861283990Sslm 2862283990Sslm /* 2863283990Sslm * If this is a SATA direct-access end device, mark it so that 2864283990Sslm * a SCSI StartStopUnit command will be sent to it when the 2865283990Sslm * driver is being shutdown. 2866283990Sslm */ 2867319436Sslm if ((scsi_cdb[0] == INQUIRY) && 2868313103Sasomers (csio->data_ptr != NULL) && 2869283990Sslm ((csio->data_ptr[0] & 0x1f) == T_DIRECT) && 2870283990Sslm (sc->mapping_table[target_id].device_info & 2871283990Sslm MPI2_SAS_DEVICE_INFO_SATA_DEVICE) && 2872283990Sslm ((sc->mapping_table[target_id].device_info & 2873283990Sslm MPI2_SAS_DEVICE_INFO_MASK_DEVICE_TYPE) == 2874283990Sslm MPI2_SAS_DEVICE_INFO_END_DEVICE)) { 2875283990Sslm target = &sassc->targets[target_id]; 2876283990Sslm target->supports_SSU = TRUE; 2877283990Sslm mpr_dprint(sc, MPR_XINFO, "Target %d supports SSU\n", 2878283990Sslm target_id); 2879283990Sslm } 2880265236Sken break; 2881265236Sken case MPI2_IOCSTATUS_SCSI_INVALID_DEVHANDLE: 2882265236Sken case MPI2_IOCSTATUS_SCSI_DEVICE_NOT_THERE: 2883265236Sken /* 2884265236Sken * If devinfo is 0 this will be a volume. In that case don't 2885265236Sken * tell CAM that the volume is not there. We want volumes to 2886265236Sken * be enumerated until they are deleted/removed, not just 2887265236Sken * failed. 2888265236Sken */ 2889265236Sken if (cm->cm_targ->devinfo == 0) 2890283990Sslm mprsas_set_ccbstatus(ccb, CAM_REQ_CMP); 2891265236Sken else 2892283990Sslm mprsas_set_ccbstatus(ccb, CAM_DEV_NOT_THERE); 2893265236Sken break; 2894265236Sken case MPI2_IOCSTATUS_INVALID_SGL: 2895265236Sken mpr_print_scsiio_cmd(sc, cm); 2896283990Sslm mprsas_set_ccbstatus(ccb, CAM_UNREC_HBA_ERROR); 2897265236Sken break; 2898265236Sken case MPI2_IOCSTATUS_SCSI_TASK_TERMINATED: 2899265236Sken /* 2900265236Sken * This is one of the responses that comes back when an I/O 2901265236Sken * has been aborted. If it is because of a timeout that we 2902265236Sken * initiated, just set the status to CAM_CMD_TIMEOUT. 2903265236Sken * Otherwise set it to CAM_REQ_ABORTED. The effect on the 2904265236Sken * command is the same (it gets retried, subject to the 2905265236Sken * retry counter), the only difference is what gets printed 2906265236Sken * on the console. 2907265236Sken */ 2908265236Sken if (cm->cm_state == MPR_CM_STATE_TIMEDOUT) 2909283990Sslm mprsas_set_ccbstatus(ccb, CAM_CMD_TIMEOUT); 2910265236Sken else 2911283990Sslm mprsas_set_ccbstatus(ccb, CAM_REQ_ABORTED); 2912265236Sken break; 2913265236Sken case MPI2_IOCSTATUS_SCSI_DATA_OVERRUN: 2914265236Sken /* resid is ignored for this condition */ 2915265236Sken csio->resid = 0; 2916283990Sslm mprsas_set_ccbstatus(ccb, CAM_DATA_RUN_ERR); 2917265236Sken break; 2918265236Sken case MPI2_IOCSTATUS_SCSI_IOC_TERMINATED: 2919265236Sken case MPI2_IOCSTATUS_SCSI_EXT_TERMINATED: 2920265236Sken /* 2921301211Sasomers * These can sometimes be transient transport-related 2922301211Sasomers * errors, and sometimes persistent drive-related errors. 2923301211Sasomers * We used to retry these without decrementing the retry 2924301211Sasomers * count by returning CAM_REQUEUE_REQ. Unfortunately, if 2925301211Sasomers * we hit a persistent drive problem that returns one of 2926301211Sasomers * these error codes, we would retry indefinitely. So, 2927301211Sasomers * return CAM_REQ_CMP_ERROR so that we decrement the retry 2928301211Sasomers * count and avoid infinite retries. We're taking the 2929301211Sasomers * potential risk of flagging false failures in the event 2930301211Sasomers * of a topology-related error (e.g. a SAS expander problem 2931301211Sasomers * causes a command addressed to a drive to fail), but 2932301211Sasomers * avoiding getting into an infinite retry loop. 2933265236Sken */ 2934301211Sasomers mprsas_set_ccbstatus(ccb, CAM_REQ_CMP_ERR); 2935265236Sken mprsas_log_command(cm, MPR_INFO, 2936319436Sslm "terminated ioc %x loginfo %x scsi %x state %x xfer %u\n", 2937319436Sslm le16toh(rep->IOCStatus), le32toh(rep->IOCLogInfo), 2938319436Sslm rep->SCSIStatus, rep->SCSIState, 2939265236Sken le32toh(rep->TransferCount)); 2940265236Sken break; 2941265236Sken case MPI2_IOCSTATUS_INVALID_FUNCTION: 2942265236Sken case MPI2_IOCSTATUS_INTERNAL_ERROR: 2943265236Sken case MPI2_IOCSTATUS_INVALID_VPID: 2944265236Sken case MPI2_IOCSTATUS_INVALID_FIELD: 2945265236Sken case MPI2_IOCSTATUS_INVALID_STATE: 2946265236Sken case MPI2_IOCSTATUS_OP_STATE_NOT_SUPPORTED: 2947265236Sken case MPI2_IOCSTATUS_SCSI_IO_DATA_ERROR: 2948265236Sken case MPI2_IOCSTATUS_SCSI_PROTOCOL_ERROR: 2949265236Sken case MPI2_IOCSTATUS_SCSI_RESIDUAL_MISMATCH: 2950265236Sken case MPI2_IOCSTATUS_SCSI_TASK_MGMT_FAILED: 2951265236Sken default: 2952265236Sken mprsas_log_command(cm, MPR_XINFO, 2953319436Sslm "completed ioc %x loginfo %x scsi %x state %x xfer %u\n", 2954319436Sslm le16toh(rep->IOCStatus), le32toh(rep->IOCLogInfo), 2955319436Sslm rep->SCSIStatus, rep->SCSIState, 2956265236Sken le32toh(rep->TransferCount)); 2957265236Sken csio->resid = cm->cm_length; 2958319436Sslm 2959319436Sslm if (scsi_cdb[0] == UNMAP && 2960319436Sslm target->is_nvme && 2961319436Sslm (csio->ccb_h.flags & CAM_DATA_MASK) == CAM_DATA_VADDR) 2962319436Sslm mprsas_set_ccbstatus(ccb, CAM_REQ_CMP); 2963319436Sslm else 2964319436Sslm mprsas_set_ccbstatus(ccb, CAM_REQ_CMP_ERR); 2965319436Sslm 2966265236Sken break; 2967265236Sken } 2968265236Sken 2969265236Sken mpr_sc_failed_io_info(sc, csio, rep, cm->cm_targ); 2970265236Sken 2971265236Sken if (sassc->flags & MPRSAS_QUEUE_FROZEN) { 2972265236Sken ccb->ccb_h.status |= CAM_RELEASE_SIMQ; 2973265236Sken sassc->flags &= ~MPRSAS_QUEUE_FROZEN; 2974265236Sken mpr_dprint(sc, MPR_XINFO, "Command completed, unfreezing SIM " 2975265236Sken "queue\n"); 2976265236Sken } 2977265236Sken 2978283990Sslm if (mprsas_get_ccbstatus(ccb) != CAM_REQ_CMP) { 2979265236Sken ccb->ccb_h.status |= CAM_DEV_QFRZN; 2980265236Sken xpt_freeze_devq(ccb->ccb_h.path, /*count*/ 1); 2981265236Sken } 2982265236Sken 2983265236Sken mpr_free_command(sc, cm); 2984265236Sken xpt_done(ccb); 2985265236Sken} 2986265236Sken 2987265236Sken#if __FreeBSD_version >= 900026 2988265236Skenstatic void 2989265236Skenmprsas_smpio_complete(struct mpr_softc *sc, struct mpr_command *cm) 2990265236Sken{ 2991265236Sken MPI2_SMP_PASSTHROUGH_REPLY *rpl; 2992265236Sken MPI2_SMP_PASSTHROUGH_REQUEST *req; 2993265236Sken uint64_t sasaddr; 2994265236Sken union ccb *ccb; 2995265236Sken 2996265236Sken ccb = cm->cm_complete_data; 2997265236Sken 2998265236Sken /* 2999265236Sken * Currently there should be no way we can hit this case. It only 3000265236Sken * happens when we have a failure to allocate chain frames, and SMP 3001265236Sken * commands require two S/G elements only. That should be handled 3002265236Sken * in the standard request size. 3003265236Sken */ 3004265236Sken if ((cm->cm_flags & MPR_CM_FLAGS_ERROR_MASK) != 0) { 3005283990Sslm mpr_dprint(sc, MPR_ERROR, "%s: cm_flags = %#x on SMP " 3006283990Sslm "request!\n", __func__, cm->cm_flags); 3007283990Sslm mprsas_set_ccbstatus(ccb, CAM_REQ_CMP_ERR); 3008265236Sken goto bailout; 3009265236Sken } 3010265236Sken 3011265236Sken rpl = (MPI2_SMP_PASSTHROUGH_REPLY *)cm->cm_reply; 3012265236Sken if (rpl == NULL) { 3013265236Sken mpr_dprint(sc, MPR_ERROR, "%s: NULL cm_reply!\n", __func__); 3014283990Sslm mprsas_set_ccbstatus(ccb, CAM_REQ_CMP_ERR); 3015265236Sken goto bailout; 3016265236Sken } 3017265236Sken 3018265236Sken req = (MPI2_SMP_PASSTHROUGH_REQUEST *)cm->cm_req; 3019265236Sken sasaddr = le32toh(req->SASAddress.Low); 3020265236Sken sasaddr |= ((uint64_t)(le32toh(req->SASAddress.High))) << 32; 3021265236Sken 3022265236Sken if ((le16toh(rpl->IOCStatus) & MPI2_IOCSTATUS_MASK) != 3023265236Sken MPI2_IOCSTATUS_SUCCESS || 3024265236Sken rpl->SASStatus != MPI2_SASSTATUS_SUCCESS) { 3025265236Sken mpr_dprint(sc, MPR_XINFO, "%s: IOCStatus %04x SASStatus %02x\n", 3026265236Sken __func__, le16toh(rpl->IOCStatus), rpl->SASStatus); 3027283990Sslm mprsas_set_ccbstatus(ccb, CAM_REQ_CMP_ERR); 3028265236Sken goto bailout; 3029265236Sken } 3030265236Sken 3031283990Sslm mpr_dprint(sc, MPR_XINFO, "%s: SMP request to SAS address %#jx " 3032283990Sslm "completed successfully\n", __func__, (uintmax_t)sasaddr); 3033265236Sken 3034265236Sken if (ccb->smpio.smp_response[2] == SMP_FR_ACCEPTED) 3035283990Sslm mprsas_set_ccbstatus(ccb, CAM_REQ_CMP); 3036265236Sken else 3037283990Sslm mprsas_set_ccbstatus(ccb, CAM_SMP_STATUS_ERROR); 3038265236Sken 3039265236Skenbailout: 3040265236Sken /* 3041265236Sken * We sync in both directions because we had DMAs in the S/G list 3042265236Sken * in both directions. 3043265236Sken */ 3044265236Sken bus_dmamap_sync(sc->buffer_dmat, cm->cm_dmamap, 3045265236Sken BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); 3046265236Sken bus_dmamap_unload(sc->buffer_dmat, cm->cm_dmamap); 3047265236Sken mpr_free_command(sc, cm); 3048265236Sken xpt_done(ccb); 3049265236Sken} 3050265236Sken 3051265236Skenstatic void 3052299962Sslmmprsas_send_smpcmd(struct mprsas_softc *sassc, union ccb *ccb, uint64_t sasaddr) 3053265236Sken{ 3054265236Sken struct mpr_command *cm; 3055265236Sken uint8_t *request, *response; 3056265236Sken MPI2_SMP_PASSTHROUGH_REQUEST *req; 3057265236Sken struct mpr_softc *sc; 3058265236Sken struct sglist *sg; 3059265236Sken int error; 3060265236Sken 3061265236Sken sc = sassc->sc; 3062265236Sken sg = NULL; 3063265236Sken error = 0; 3064265236Sken 3065265730Sken#if (__FreeBSD_version >= 1000028) || \ 3066265730Sken ((__FreeBSD_version >= 902001) && (__FreeBSD_version < 1000000)) 3067265236Sken switch (ccb->ccb_h.flags & CAM_DATA_MASK) { 3068265236Sken case CAM_DATA_PADDR: 3069265236Sken case CAM_DATA_SG_PADDR: 3070265236Sken /* 3071265236Sken * XXX We don't yet support physical addresses here. 3072265236Sken */ 3073265236Sken mpr_dprint(sc, MPR_ERROR, "%s: physical addresses not " 3074265236Sken "supported\n", __func__); 3075283990Sslm mprsas_set_ccbstatus(ccb, CAM_REQ_INVALID); 3076265236Sken xpt_done(ccb); 3077265236Sken return; 3078265236Sken case CAM_DATA_SG: 3079265236Sken /* 3080265236Sken * The chip does not support more than one buffer for the 3081265236Sken * request or response. 3082265236Sken */ 3083265236Sken if ((ccb->smpio.smp_request_sglist_cnt > 1) 3084265236Sken || (ccb->smpio.smp_response_sglist_cnt > 1)) { 3085299962Sslm mpr_dprint(sc, MPR_ERROR, "%s: multiple request or " 3086299962Sslm "response buffer segments not supported for SMP\n", 3087299962Sslm __func__); 3088283990Sslm mprsas_set_ccbstatus(ccb, CAM_REQ_INVALID); 3089265236Sken xpt_done(ccb); 3090265236Sken return; 3091265236Sken } 3092265236Sken 3093265236Sken /* 3094265236Sken * The CAM_SCATTER_VALID flag was originally implemented 3095265236Sken * for the XPT_SCSI_IO CCB, which only has one data pointer. 3096265236Sken * We have two. So, just take that flag to mean that we 3097265236Sken * might have S/G lists, and look at the S/G segment count 3098265236Sken * to figure out whether that is the case for each individual 3099265236Sken * buffer. 3100265236Sken */ 3101265236Sken if (ccb->smpio.smp_request_sglist_cnt != 0) { 3102265236Sken bus_dma_segment_t *req_sg; 3103265236Sken 3104265236Sken req_sg = (bus_dma_segment_t *)ccb->smpio.smp_request; 3105265236Sken request = (uint8_t *)(uintptr_t)req_sg[0].ds_addr; 3106265236Sken } else 3107265236Sken request = ccb->smpio.smp_request; 3108265236Sken 3109265236Sken if (ccb->smpio.smp_response_sglist_cnt != 0) { 3110265236Sken bus_dma_segment_t *rsp_sg; 3111265236Sken 3112265236Sken rsp_sg = (bus_dma_segment_t *)ccb->smpio.smp_response; 3113265236Sken response = (uint8_t *)(uintptr_t)rsp_sg[0].ds_addr; 3114265236Sken } else 3115265236Sken response = ccb->smpio.smp_response; 3116265236Sken break; 3117265236Sken case CAM_DATA_VADDR: 3118265236Sken request = ccb->smpio.smp_request; 3119265236Sken response = ccb->smpio.smp_response; 3120265236Sken break; 3121265236Sken default: 3122283990Sslm mprsas_set_ccbstatus(ccb, CAM_REQ_INVALID); 3123265236Sken xpt_done(ccb); 3124265236Sken return; 3125265236Sken } 3126265730Sken#else /* __FreeBSD_version < 1000028 */ 3127265236Sken /* 3128265236Sken * XXX We don't yet support physical addresses here. 3129265236Sken */ 3130265236Sken if (ccb->ccb_h.flags & (CAM_DATA_PHYS|CAM_SG_LIST_PHYS)) { 3131283990Sslm mpr_dprint(sc, MPR_ERROR, "%s: physical addresses not " 3132283990Sslm "supported\n", __func__); 3133283990Sslm mprsas_set_ccbstatus(ccb, CAM_REQ_INVALID); 3134265236Sken xpt_done(ccb); 3135265236Sken return; 3136265236Sken } 3137265236Sken 3138265236Sken /* 3139265236Sken * If the user wants to send an S/G list, check to make sure they 3140265236Sken * have single buffers. 3141265236Sken */ 3142265236Sken if (ccb->ccb_h.flags & CAM_SCATTER_VALID) { 3143265236Sken /* 3144265236Sken * The chip does not support more than one buffer for the 3145265236Sken * request or response. 3146265236Sken */ 3147265236Sken if ((ccb->smpio.smp_request_sglist_cnt > 1) 3148265236Sken || (ccb->smpio.smp_response_sglist_cnt > 1)) { 3149265236Sken mpr_dprint(sc, MPR_ERROR, "%s: multiple request or " 3150265236Sken "response buffer segments not supported for SMP\n", 3151265236Sken __func__); 3152283990Sslm mprsas_set_ccbstatus(ccb, CAM_REQ_INVALID); 3153265236Sken xpt_done(ccb); 3154265236Sken return; 3155265236Sken } 3156265236Sken 3157265236Sken /* 3158265236Sken * The CAM_SCATTER_VALID flag was originally implemented 3159265236Sken * for the XPT_SCSI_IO CCB, which only has one data pointer. 3160265236Sken * We have two. So, just take that flag to mean that we 3161265236Sken * might have S/G lists, and look at the S/G segment count 3162265236Sken * to figure out whether that is the case for each individual 3163265236Sken * buffer. 3164265236Sken */ 3165265236Sken if (ccb->smpio.smp_request_sglist_cnt != 0) { 3166265236Sken bus_dma_segment_t *req_sg; 3167265236Sken 3168265236Sken req_sg = (bus_dma_segment_t *)ccb->smpio.smp_request; 3169265730Sken request = (uint8_t *)(uintptr_t)req_sg[0].ds_addr; 3170265236Sken } else 3171265236Sken request = ccb->smpio.smp_request; 3172265236Sken 3173265236Sken if (ccb->smpio.smp_response_sglist_cnt != 0) { 3174265236Sken bus_dma_segment_t *rsp_sg; 3175265236Sken 3176265236Sken rsp_sg = (bus_dma_segment_t *)ccb->smpio.smp_response; 3177265730Sken response = (uint8_t *)(uintptr_t)rsp_sg[0].ds_addr; 3178265236Sken } else 3179265236Sken response = ccb->smpio.smp_response; 3180265236Sken } else { 3181265236Sken request = ccb->smpio.smp_request; 3182265236Sken response = ccb->smpio.smp_response; 3183265236Sken } 3184265730Sken#endif /* __FreeBSD_version < 1000028 */ 3185265236Sken 3186265236Sken cm = mpr_alloc_command(sc); 3187265236Sken if (cm == NULL) { 3188299962Sslm mpr_dprint(sc, MPR_ERROR, "%s: cannot allocate command\n", 3189299962Sslm __func__); 3190283990Sslm mprsas_set_ccbstatus(ccb, CAM_RESRC_UNAVAIL); 3191265236Sken xpt_done(ccb); 3192265236Sken return; 3193265236Sken } 3194265236Sken 3195265236Sken req = (MPI2_SMP_PASSTHROUGH_REQUEST *)cm->cm_req; 3196265236Sken bzero(req, sizeof(*req)); 3197265236Sken req->Function = MPI2_FUNCTION_SMP_PASSTHROUGH; 3198265236Sken 3199265236Sken /* Allow the chip to use any route to this SAS address. */ 3200265236Sken req->PhysicalPort = 0xff; 3201265236Sken 3202265236Sken req->RequestDataLength = htole16(ccb->smpio.smp_request_len); 3203265236Sken req->SGLFlags = 3204265236Sken MPI2_SGLFLAGS_SYSTEM_ADDRESS_SPACE | MPI2_SGLFLAGS_SGL_TYPE_MPI; 3205265236Sken 3206265236Sken mpr_dprint(sc, MPR_XINFO, "%s: sending SMP request to SAS address " 3207265236Sken "%#jx\n", __func__, (uintmax_t)sasaddr); 3208265236Sken 3209265236Sken mpr_init_sge(cm, req, &req->SGL); 3210265236Sken 3211265236Sken /* 3212265236Sken * Set up a uio to pass into mpr_map_command(). This allows us to 3213265236Sken * do one map command, and one busdma call in there. 3214265236Sken */ 3215265236Sken cm->cm_uio.uio_iov = cm->cm_iovec; 3216265236Sken cm->cm_uio.uio_iovcnt = 2; 3217265236Sken cm->cm_uio.uio_segflg = UIO_SYSSPACE; 3218265236Sken 3219265236Sken /* 3220265236Sken * The read/write flag isn't used by busdma, but set it just in 3221265236Sken * case. This isn't exactly accurate, either, since we're going in 3222265236Sken * both directions. 3223265236Sken */ 3224265236Sken cm->cm_uio.uio_rw = UIO_WRITE; 3225265236Sken 3226265236Sken cm->cm_iovec[0].iov_base = request; 3227265236Sken cm->cm_iovec[0].iov_len = le16toh(req->RequestDataLength); 3228265236Sken cm->cm_iovec[1].iov_base = response; 3229265236Sken cm->cm_iovec[1].iov_len = ccb->smpio.smp_response_len; 3230265236Sken 3231265236Sken cm->cm_uio.uio_resid = cm->cm_iovec[0].iov_len + 3232265236Sken cm->cm_iovec[1].iov_len; 3233265236Sken 3234265236Sken /* 3235265236Sken * Trigger a warning message in mpr_data_cb() for the user if we 3236265236Sken * wind up exceeding two S/G segments. The chip expects one 3237265236Sken * segment for the request and another for the response. 3238265236Sken */ 3239265236Sken cm->cm_max_segs = 2; 3240265236Sken 3241265236Sken cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 3242265236Sken cm->cm_complete = mprsas_smpio_complete; 3243265236Sken cm->cm_complete_data = ccb; 3244265236Sken 3245265236Sken /* 3246265236Sken * Tell the mapping code that we're using a uio, and that this is 3247265236Sken * an SMP passthrough request. There is a little special-case 3248265236Sken * logic there (in mpr_data_cb()) to handle the bidirectional 3249265236Sken * transfer. 3250265236Sken */ 3251265236Sken cm->cm_flags |= MPR_CM_FLAGS_USE_UIO | MPR_CM_FLAGS_SMP_PASS | 3252265236Sken MPR_CM_FLAGS_DATAIN | MPR_CM_FLAGS_DATAOUT; 3253265236Sken 3254265236Sken /* The chip data format is little endian. */ 3255265236Sken req->SASAddress.High = htole32(sasaddr >> 32); 3256265236Sken req->SASAddress.Low = htole32(sasaddr); 3257265236Sken 3258265236Sken /* 3259265236Sken * XXX Note that we don't have a timeout/abort mechanism here. 3260265236Sken * From the manual, it looks like task management requests only 3261265236Sken * work for SCSI IO and SATA passthrough requests. We may need to 3262265236Sken * have a mechanism to retry requests in the event of a chip reset 3263265236Sken * at least. Hopefully the chip will insure that any errors short 3264265236Sken * of that are relayed back to the driver. 3265265236Sken */ 3266265236Sken error = mpr_map_command(sc, cm); 3267265236Sken if ((error != 0) && (error != EINPROGRESS)) { 3268265236Sken mpr_dprint(sc, MPR_ERROR, "%s: error %d returned from " 3269265236Sken "mpr_map_command()\n", __func__, error); 3270265236Sken goto bailout_error; 3271265236Sken } 3272265236Sken 3273265236Sken return; 3274265236Sken 3275265236Skenbailout_error: 3276265236Sken mpr_free_command(sc, cm); 3277283990Sslm mprsas_set_ccbstatus(ccb, CAM_RESRC_UNAVAIL); 3278265236Sken xpt_done(ccb); 3279265236Sken return; 3280265236Sken} 3281265236Sken 3282265236Skenstatic void 3283265236Skenmprsas_action_smpio(struct mprsas_softc *sassc, union ccb *ccb) 3284265236Sken{ 3285265236Sken struct mpr_softc *sc; 3286265236Sken struct mprsas_target *targ; 3287265236Sken uint64_t sasaddr = 0; 3288265236Sken 3289265236Sken sc = sassc->sc; 3290265236Sken 3291265236Sken /* 3292265236Sken * Make sure the target exists. 3293265236Sken */ 3294265236Sken KASSERT(ccb->ccb_h.target_id < sassc->maxtargets, 3295265236Sken ("Target %d out of bounds in XPT_SMP_IO\n", ccb->ccb_h.target_id)); 3296265236Sken targ = &sassc->targets[ccb->ccb_h.target_id]; 3297265236Sken if (targ->handle == 0x0) { 3298265236Sken mpr_dprint(sc, MPR_ERROR, "%s: target %d does not exist!\n", 3299265236Sken __func__, ccb->ccb_h.target_id); 3300283990Sslm mprsas_set_ccbstatus(ccb, CAM_SEL_TIMEOUT); 3301265236Sken xpt_done(ccb); 3302265236Sken return; 3303265236Sken } 3304265236Sken 3305265236Sken /* 3306265236Sken * If this device has an embedded SMP target, we'll talk to it 3307265236Sken * directly. 3308265236Sken * figure out what the expander's address is. 3309265236Sken */ 3310265236Sken if ((targ->devinfo & MPI2_SAS_DEVICE_INFO_SMP_TARGET) != 0) 3311265236Sken sasaddr = targ->sasaddr; 3312265236Sken 3313265236Sken /* 3314265236Sken * If we don't have a SAS address for the expander yet, try 3315265236Sken * grabbing it from the page 0x83 information cached in the 3316265236Sken * transport layer for this target. LSI expanders report the 3317265236Sken * expander SAS address as the port-associated SAS address in 3318265236Sken * Inquiry VPD page 0x83. Maxim expanders don't report it in page 3319265236Sken * 0x83. 3320265236Sken * 3321265236Sken * XXX KDM disable this for now, but leave it commented out so that 3322265236Sken * it is obvious that this is another possible way to get the SAS 3323265236Sken * address. 3324265236Sken * 3325265236Sken * The parent handle method below is a little more reliable, and 3326265236Sken * the other benefit is that it works for devices other than SES 3327265236Sken * devices. So you can send a SMP request to a da(4) device and it 3328265236Sken * will get routed to the expander that device is attached to. 3329265236Sken * (Assuming the da(4) device doesn't contain an SMP target...) 3330265236Sken */ 3331265236Sken#if 0 3332265236Sken if (sasaddr == 0) 3333265236Sken sasaddr = xpt_path_sas_addr(ccb->ccb_h.path); 3334265236Sken#endif 3335265236Sken 3336265236Sken /* 3337265236Sken * If we still don't have a SAS address for the expander, look for 3338265236Sken * the parent device of this device, which is probably the expander. 3339265236Sken */ 3340265236Sken if (sasaddr == 0) { 3341265236Sken#ifdef OLD_MPR_PROBE 3342265236Sken struct mprsas_target *parent_target; 3343265236Sken#endif 3344265236Sken 3345265236Sken if (targ->parent_handle == 0x0) { 3346265236Sken mpr_dprint(sc, MPR_ERROR, "%s: handle %d does not have " 3347265236Sken "a valid parent handle!\n", __func__, targ->handle); 3348283990Sslm mprsas_set_ccbstatus(ccb, CAM_DEV_NOT_THERE); 3349265236Sken goto bailout; 3350265236Sken } 3351265236Sken#ifdef OLD_MPR_PROBE 3352265236Sken parent_target = mprsas_find_target_by_handle(sassc, 0, 3353265236Sken targ->parent_handle); 3354265236Sken 3355265236Sken if (parent_target == NULL) { 3356265236Sken mpr_dprint(sc, MPR_ERROR, "%s: handle %d does not have " 3357265236Sken "a valid parent target!\n", __func__, targ->handle); 3358283990Sslm mprsas_set_ccbstatus(ccb, CAM_DEV_NOT_THERE); 3359265236Sken goto bailout; 3360265236Sken } 3361265236Sken 3362265236Sken if ((parent_target->devinfo & 3363265236Sken MPI2_SAS_DEVICE_INFO_SMP_TARGET) == 0) { 3364265236Sken mpr_dprint(sc, MPR_ERROR, "%s: handle %d parent %d " 3365265236Sken "does not have an SMP target!\n", __func__, 3366265236Sken targ->handle, parent_target->handle); 3367283990Sslm mprsas_set_ccbstatus(ccb, CAM_DEV_NOT_THERE); 3368265236Sken goto bailout; 3369265236Sken } 3370265236Sken 3371265236Sken sasaddr = parent_target->sasaddr; 3372265236Sken#else /* OLD_MPR_PROBE */ 3373265236Sken if ((targ->parent_devinfo & 3374265236Sken MPI2_SAS_DEVICE_INFO_SMP_TARGET) == 0) { 3375265236Sken mpr_dprint(sc, MPR_ERROR, "%s: handle %d parent %d " 3376265236Sken "does not have an SMP target!\n", __func__, 3377265236Sken targ->handle, targ->parent_handle); 3378283990Sslm mprsas_set_ccbstatus(ccb, CAM_DEV_NOT_THERE); 3379265236Sken goto bailout; 3380265236Sken 3381265236Sken } 3382265236Sken if (targ->parent_sasaddr == 0x0) { 3383265236Sken mpr_dprint(sc, MPR_ERROR, "%s: handle %d parent handle " 3384265236Sken "%d does not have a valid SAS address!\n", __func__, 3385265236Sken targ->handle, targ->parent_handle); 3386283990Sslm mprsas_set_ccbstatus(ccb, CAM_DEV_NOT_THERE); 3387265236Sken goto bailout; 3388265236Sken } 3389265236Sken 3390265236Sken sasaddr = targ->parent_sasaddr; 3391265236Sken#endif /* OLD_MPR_PROBE */ 3392265236Sken 3393265236Sken } 3394265236Sken 3395265236Sken if (sasaddr == 0) { 3396265236Sken mpr_dprint(sc, MPR_INFO, "%s: unable to find SAS address for " 3397265236Sken "handle %d\n", __func__, targ->handle); 3398283990Sslm mprsas_set_ccbstatus(ccb, CAM_DEV_NOT_THERE); 3399265236Sken goto bailout; 3400265236Sken } 3401265236Sken mprsas_send_smpcmd(sassc, ccb, sasaddr); 3402265236Sken 3403265236Sken return; 3404265236Sken 3405265236Skenbailout: 3406265236Sken xpt_done(ccb); 3407265236Sken 3408265236Sken} 3409265236Sken#endif //__FreeBSD_version >= 900026 3410265236Sken 3411265236Skenstatic void 3412265236Skenmprsas_action_resetdev(struct mprsas_softc *sassc, union ccb *ccb) 3413265236Sken{ 3414265236Sken MPI2_SCSI_TASK_MANAGE_REQUEST *req; 3415265236Sken struct mpr_softc *sc; 3416265236Sken struct mpr_command *tm; 3417265236Sken struct mprsas_target *targ; 3418265236Sken 3419265236Sken MPR_FUNCTRACE(sassc->sc); 3420265236Sken mtx_assert(&sassc->sc->mpr_mtx, MA_OWNED); 3421265236Sken 3422299962Sslm KASSERT(ccb->ccb_h.target_id < sassc->maxtargets, ("Target %d out of " 3423299962Sslm "bounds in XPT_RESET_DEV\n", ccb->ccb_h.target_id)); 3424265236Sken sc = sassc->sc; 3425265236Sken tm = mpr_alloc_command(sc); 3426265236Sken if (tm == NULL) { 3427299962Sslm mpr_dprint(sc, MPR_ERROR, "command alloc failure in " 3428299962Sslm "mprsas_action_resetdev\n"); 3429283990Sslm mprsas_set_ccbstatus(ccb, CAM_RESRC_UNAVAIL); 3430265236Sken xpt_done(ccb); 3431265236Sken return; 3432265236Sken } 3433265236Sken 3434265236Sken targ = &sassc->targets[ccb->ccb_h.target_id]; 3435265236Sken req = (MPI2_SCSI_TASK_MANAGE_REQUEST *)tm->cm_req; 3436265236Sken req->DevHandle = htole16(targ->handle); 3437265236Sken req->Function = MPI2_FUNCTION_SCSI_TASK_MGMT; 3438265236Sken req->TaskType = MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET; 3439265236Sken 3440265236Sken /* SAS Hard Link Reset / SATA Link Reset */ 3441265236Sken req->MsgFlags = MPI2_SCSITASKMGMT_MSGFLAGS_LINK_RESET; 3442265236Sken 3443265236Sken tm->cm_data = NULL; 3444265236Sken tm->cm_desc.HighPriority.RequestFlags = 3445265236Sken MPI2_REQ_DESCRIPT_FLAGS_HIGH_PRIORITY; 3446265236Sken tm->cm_complete = mprsas_resetdev_complete; 3447265236Sken tm->cm_complete_data = ccb; 3448283990Sslm 3449283990Sslm mpr_dprint(sc, MPR_INFO, "%s: Sending reset for target ID %d\n", 3450283990Sslm __func__, targ->tid); 3451265236Sken tm->cm_targ = targ; 3452283990Sslm targ->flags |= MPRSAS_TARGET_INRESET; 3453283990Sslm 3454265236Sken mpr_map_command(sc, tm); 3455265236Sken} 3456265236Sken 3457265236Skenstatic void 3458265236Skenmprsas_resetdev_complete(struct mpr_softc *sc, struct mpr_command *tm) 3459265236Sken{ 3460265236Sken MPI2_SCSI_TASK_MANAGE_REPLY *resp; 3461265236Sken union ccb *ccb; 3462265236Sken 3463265236Sken MPR_FUNCTRACE(sc); 3464265236Sken mtx_assert(&sc->mpr_mtx, MA_OWNED); 3465265236Sken 3466265236Sken resp = (MPI2_SCSI_TASK_MANAGE_REPLY *)tm->cm_reply; 3467265236Sken ccb = tm->cm_complete_data; 3468265236Sken 3469265236Sken /* 3470265236Sken * Currently there should be no way we can hit this case. It only 3471265236Sken * happens when we have a failure to allocate chain frames, and 3472265236Sken * task management commands don't have S/G lists. 3473265236Sken */ 3474265236Sken if ((tm->cm_flags & MPR_CM_FLAGS_ERROR_MASK) != 0) { 3475265236Sken MPI2_SCSI_TASK_MANAGE_REQUEST *req; 3476265236Sken 3477265236Sken req = (MPI2_SCSI_TASK_MANAGE_REQUEST *)tm->cm_req; 3478265236Sken 3479265236Sken mpr_dprint(sc, MPR_ERROR, "%s: cm_flags = %#x for reset of " 3480265236Sken "handle %#04x! This should not happen!\n", __func__, 3481265236Sken tm->cm_flags, req->DevHandle); 3482283990Sslm mprsas_set_ccbstatus(ccb, CAM_REQ_CMP_ERR); 3483265236Sken goto bailout; 3484265236Sken } 3485265236Sken 3486299962Sslm mpr_dprint(sc, MPR_XINFO, "%s: IOCStatus = 0x%x ResponseCode = 0x%x\n", 3487299962Sslm __func__, le16toh(resp->IOCStatus), le32toh(resp->ResponseCode)); 3488265236Sken 3489265236Sken if (le32toh(resp->ResponseCode) == MPI2_SCSITASKMGMT_RSP_TM_COMPLETE) { 3490283990Sslm mprsas_set_ccbstatus(ccb, CAM_REQ_CMP); 3491265236Sken mprsas_announce_reset(sc, AC_SENT_BDR, tm->cm_targ->tid, 3492265236Sken CAM_LUN_WILDCARD); 3493265236Sken } 3494265236Sken else 3495283990Sslm mprsas_set_ccbstatus(ccb, CAM_REQ_CMP_ERR); 3496265236Sken 3497265236Skenbailout: 3498265236Sken 3499265236Sken mprsas_free_tm(sc, tm); 3500265236Sken xpt_done(ccb); 3501265236Sken} 3502265236Sken 3503265236Skenstatic void 3504265236Skenmprsas_poll(struct cam_sim *sim) 3505265236Sken{ 3506265236Sken struct mprsas_softc *sassc; 3507265236Sken 3508265236Sken sassc = cam_sim_softc(sim); 3509265236Sken 3510265236Sken if (sassc->sc->mpr_debug & MPR_TRACE) { 3511265236Sken /* frequent debug messages during a panic just slow 3512265236Sken * everything down too much. 3513265236Sken */ 3514283990Sslm mpr_dprint(sassc->sc, MPR_XINFO, "%s clearing MPR_TRACE\n", 3515283990Sslm __func__); 3516265236Sken sassc->sc->mpr_debug &= ~MPR_TRACE; 3517265236Sken } 3518265236Sken 3519265236Sken mpr_intr_locked(sassc->sc); 3520265236Sken} 3521265236Sken 3522265236Skenstatic void 3523265236Skenmprsas_async(void *callback_arg, uint32_t code, struct cam_path *path, 3524265236Sken void *arg) 3525265236Sken{ 3526265236Sken struct mpr_softc *sc; 3527265236Sken 3528265236Sken sc = (struct mpr_softc *)callback_arg; 3529265236Sken 3530265236Sken switch (code) { 3531265236Sken#if (__FreeBSD_version >= 1000006) || \ 3532265236Sken ((__FreeBSD_version >= 901503) && (__FreeBSD_version < 1000000)) 3533265236Sken case AC_ADVINFO_CHANGED: { 3534265236Sken struct mprsas_target *target; 3535265236Sken struct mprsas_softc *sassc; 3536265236Sken struct scsi_read_capacity_data_long rcap_buf; 3537265236Sken struct ccb_dev_advinfo cdai; 3538265236Sken struct mprsas_lun *lun; 3539265236Sken lun_id_t lunid; 3540265236Sken int found_lun; 3541265236Sken uintptr_t buftype; 3542265236Sken 3543265236Sken buftype = (uintptr_t)arg; 3544265236Sken 3545265236Sken found_lun = 0; 3546265236Sken sassc = sc->sassc; 3547265236Sken 3548265236Sken /* 3549265236Sken * We're only interested in read capacity data changes. 3550265236Sken */ 3551265236Sken if (buftype != CDAI_TYPE_RCAPLONG) 3552265236Sken break; 3553265236Sken 3554265236Sken /* 3555265730Sken * See the comment in mpr_attach_sas() for a detailed 3556265730Sken * explanation. In these versions of FreeBSD we register 3557265730Sken * for all events and filter out the events that don't 3558265730Sken * apply to us. 3559265730Sken */ 3560265730Sken#if (__FreeBSD_version < 1000703) || \ 3561265730Sken ((__FreeBSD_version >= 1100000) && (__FreeBSD_version < 1100002)) 3562265730Sken if (xpt_path_path_id(path) != sassc->sim->path_id) 3563265730Sken break; 3564265730Sken#endif 3565265730Sken 3566265730Sken /* 3567265236Sken * We should have a handle for this, but check to make sure. 3568265236Sken */ 3569265236Sken KASSERT(xpt_path_target_id(path) < sassc->maxtargets, 3570265236Sken ("Target %d out of bounds in mprsas_async\n", 3571265236Sken xpt_path_target_id(path))); 3572265236Sken target = &sassc->targets[xpt_path_target_id(path)]; 3573265236Sken if (target->handle == 0) 3574265236Sken break; 3575265236Sken 3576265236Sken lunid = xpt_path_lun_id(path); 3577265236Sken 3578265236Sken SLIST_FOREACH(lun, &target->luns, lun_link) { 3579265236Sken if (lun->lun_id == lunid) { 3580265236Sken found_lun = 1; 3581265236Sken break; 3582265236Sken } 3583265236Sken } 3584265236Sken 3585265236Sken if (found_lun == 0) { 3586265236Sken lun = malloc(sizeof(struct mprsas_lun), M_MPR, 3587265236Sken M_NOWAIT | M_ZERO); 3588265236Sken if (lun == NULL) { 3589265236Sken mpr_dprint(sc, MPR_ERROR, "Unable to alloc " 3590265236Sken "LUN for EEDP support.\n"); 3591265236Sken break; 3592265236Sken } 3593265236Sken lun->lun_id = lunid; 3594265236Sken SLIST_INSERT_HEAD(&target->luns, lun, lun_link); 3595265236Sken } 3596265236Sken 3597265236Sken bzero(&rcap_buf, sizeof(rcap_buf)); 3598265236Sken xpt_setup_ccb(&cdai.ccb_h, path, CAM_PRIORITY_NORMAL); 3599265236Sken cdai.ccb_h.func_code = XPT_DEV_ADVINFO; 3600265236Sken cdai.ccb_h.flags = CAM_DIR_IN; 3601265236Sken cdai.buftype = CDAI_TYPE_RCAPLONG; 3602280448Sken#if (__FreeBSD_version >= 1100061) || \ 3603280448Sken ((__FreeBSD_version >= 1001510) && (__FreeBSD_version < 1100000)) 3604279329Sken cdai.flags = CDAI_FLAG_NONE; 3605279329Sken#else 3606265236Sken cdai.flags = 0; 3607279329Sken#endif 3608265236Sken cdai.bufsiz = sizeof(rcap_buf); 3609265236Sken cdai.buf = (uint8_t *)&rcap_buf; 3610265236Sken xpt_action((union ccb *)&cdai); 3611265236Sken if ((cdai.ccb_h.status & CAM_DEV_QFRZN) != 0) 3612265236Sken cam_release_devq(cdai.ccb_h.path, 0, 0, 0, FALSE); 3613265236Sken 3614283990Sslm if ((mprsas_get_ccbstatus((union ccb *)&cdai) == CAM_REQ_CMP) 3615265236Sken && (rcap_buf.prot & SRC16_PROT_EN)) { 3616265236Sken lun->eedp_formatted = TRUE; 3617265236Sken lun->eedp_block_size = scsi_4btoul(rcap_buf.length); 3618265236Sken } else { 3619265236Sken lun->eedp_formatted = FALSE; 3620265236Sken lun->eedp_block_size = 0; 3621265236Sken } 3622265236Sken break; 3623265236Sken } 3624265236Sken#endif 3625265236Sken case AC_FOUND_DEVICE: { 3626265236Sken struct ccb_getdev *cgd; 3627265236Sken 3628265730Sken /* 3629265730Sken * See the comment in mpr_attach_sas() for a detailed 3630265730Sken * explanation. In these versions of FreeBSD we register 3631265730Sken * for all events and filter out the events that don't 3632265730Sken * apply to us. 3633265730Sken */ 3634265730Sken#if (__FreeBSD_version < 1000703) || \ 3635265730Sken ((__FreeBSD_version >= 1100000) && (__FreeBSD_version < 1100002)) 3636265730Sken if (xpt_path_path_id(path) != sc->sassc->sim->path_id) 3637265730Sken break; 3638265730Sken#endif 3639265730Sken 3640265236Sken cgd = arg; 3641265236Sken#if (__FreeBSD_version < 901503) || \ 3642265236Sken ((__FreeBSD_version >= 1000000) && (__FreeBSD_version < 1000006)) 3643265236Sken mprsas_check_eedp(sc, path, cgd); 3644265236Sken#endif 3645265236Sken break; 3646265236Sken } 3647265236Sken default: 3648265236Sken break; 3649265236Sken } 3650265236Sken} 3651265236Sken 3652265236Sken#if (__FreeBSD_version < 901503) || \ 3653265236Sken ((__FreeBSD_version >= 1000000) && (__FreeBSD_version < 1000006)) 3654265236Skenstatic void 3655265236Skenmprsas_check_eedp(struct mpr_softc *sc, struct cam_path *path, 3656265236Sken struct ccb_getdev *cgd) 3657265236Sken{ 3658265236Sken struct mprsas_softc *sassc = sc->sassc; 3659265236Sken struct ccb_scsiio *csio; 3660265236Sken struct scsi_read_capacity_16 *scsi_cmd; 3661265236Sken struct scsi_read_capacity_eedp *rcap_buf; 3662265236Sken path_id_t pathid; 3663265236Sken target_id_t targetid; 3664265236Sken lun_id_t lunid; 3665265236Sken union ccb *ccb; 3666265236Sken struct cam_path *local_path; 3667265236Sken struct mprsas_target *target; 3668265236Sken struct mprsas_lun *lun; 3669265236Sken uint8_t found_lun; 3670265236Sken char path_str[64]; 3671265236Sken 3672265236Sken pathid = cam_sim_path(sassc->sim); 3673265236Sken targetid = xpt_path_target_id(path); 3674265236Sken lunid = xpt_path_lun_id(path); 3675265236Sken 3676299962Sslm KASSERT(targetid < sassc->maxtargets, ("Target %d out of bounds in " 3677299962Sslm "mprsas_check_eedp\n", targetid)); 3678265236Sken target = &sassc->targets[targetid]; 3679265236Sken if (target->handle == 0x0) 3680265236Sken return; 3681265236Sken 3682265236Sken /* 3683265236Sken * Determine if the device is EEDP capable. 3684265236Sken * 3685265236Sken * If this flag is set in the inquiry data, the device supports 3686265236Sken * protection information, and must support the 16 byte read capacity 3687299962Sslm * command, otherwise continue without sending read cap 16. 3688265236Sken */ 3689265236Sken if ((cgd->inq_data.spc3_flags & SPC3_SID_PROTECT) == 0) 3690265236Sken return; 3691265236Sken 3692265236Sken /* 3693265236Sken * Issue a READ CAPACITY 16 command. This info is used to determine if 3694265236Sken * the LUN is formatted for EEDP support. 3695265236Sken */ 3696265236Sken ccb = xpt_alloc_ccb_nowait(); 3697265236Sken if (ccb == NULL) { 3698265236Sken mpr_dprint(sc, MPR_ERROR, "Unable to alloc CCB for EEDP " 3699265236Sken "support.\n"); 3700265236Sken return; 3701265236Sken } 3702265236Sken 3703299962Sslm if (xpt_create_path(&local_path, xpt_periph, pathid, targetid, lunid) != 3704299962Sslm CAM_REQ_CMP) { 3705265236Sken mpr_dprint(sc, MPR_ERROR, "Unable to create path for EEDP " 3706299962Sslm "support.\n"); 3707265236Sken xpt_free_ccb(ccb); 3708265236Sken return; 3709265236Sken } 3710265236Sken 3711265236Sken /* 3712265236Sken * If LUN is already in list, don't create a new one. 3713265236Sken */ 3714265236Sken found_lun = FALSE; 3715265236Sken SLIST_FOREACH(lun, &target->luns, lun_link) { 3716265236Sken if (lun->lun_id == lunid) { 3717265236Sken found_lun = TRUE; 3718265236Sken break; 3719265236Sken } 3720265236Sken } 3721265236Sken if (!found_lun) { 3722265236Sken lun = malloc(sizeof(struct mprsas_lun), M_MPR, 3723265236Sken M_NOWAIT | M_ZERO); 3724265236Sken if (lun == NULL) { 3725265236Sken mpr_dprint(sc, MPR_ERROR, "Unable to alloc LUN for " 3726265236Sken "EEDP support.\n"); 3727265236Sken xpt_free_path(local_path); 3728265236Sken xpt_free_ccb(ccb); 3729265236Sken return; 3730265236Sken } 3731265236Sken lun->lun_id = lunid; 3732265236Sken SLIST_INSERT_HEAD(&target->luns, lun, lun_link); 3733265236Sken } 3734265236Sken 3735265236Sken xpt_path_string(local_path, path_str, sizeof(path_str)); 3736265236Sken mpr_dprint(sc, MPR_INFO, "Sending read cap: path %s handle %d\n", 3737265236Sken path_str, target->handle); 3738265236Sken 3739265236Sken /* 3740265236Sken * Issue a READ CAPACITY 16 command for the LUN. The 3741265236Sken * mprsas_read_cap_done function will load the read cap info into the 3742265236Sken * LUN struct. 3743265236Sken */ 3744265236Sken rcap_buf = malloc(sizeof(struct scsi_read_capacity_eedp), M_MPR, 3745265236Sken M_NOWAIT | M_ZERO); 3746265236Sken if (rcap_buf == NULL) { 3747283990Sslm mpr_dprint(sc, MPR_ERROR, "Unable to alloc read capacity " 3748265236Sken "buffer for EEDP support.\n"); 3749265236Sken xpt_free_path(ccb->ccb_h.path); 3750265236Sken xpt_free_ccb(ccb); 3751265236Sken return; 3752265236Sken } 3753265236Sken xpt_setup_ccb(&ccb->ccb_h, local_path, CAM_PRIORITY_XPT); 3754265236Sken csio = &ccb->csio; 3755265236Sken csio->ccb_h.func_code = XPT_SCSI_IO; 3756265236Sken csio->ccb_h.flags = CAM_DIR_IN; 3757265236Sken csio->ccb_h.retry_count = 4; 3758265236Sken csio->ccb_h.cbfcnp = mprsas_read_cap_done; 3759265236Sken csio->ccb_h.timeout = 60000; 3760265236Sken csio->data_ptr = (uint8_t *)rcap_buf; 3761265236Sken csio->dxfer_len = sizeof(struct scsi_read_capacity_eedp); 3762265236Sken csio->sense_len = MPR_SENSE_LEN; 3763265236Sken csio->cdb_len = sizeof(*scsi_cmd); 3764265236Sken csio->tag_action = MSG_SIMPLE_Q_TAG; 3765265236Sken 3766265236Sken scsi_cmd = (struct scsi_read_capacity_16 *)&csio->cdb_io.cdb_bytes; 3767265236Sken bzero(scsi_cmd, sizeof(*scsi_cmd)); 3768265236Sken scsi_cmd->opcode = 0x9E; 3769265236Sken scsi_cmd->service_action = SRC16_SERVICE_ACTION; 3770265236Sken ((uint8_t *)scsi_cmd)[13] = sizeof(struct scsi_read_capacity_eedp); 3771265236Sken 3772265236Sken ccb->ccb_h.ppriv_ptr1 = sassc; 3773265236Sken xpt_action(ccb); 3774265236Sken} 3775265236Sken 3776265236Skenstatic void 3777265236Skenmprsas_read_cap_done(struct cam_periph *periph, union ccb *done_ccb) 3778265236Sken{ 3779265236Sken struct mprsas_softc *sassc; 3780265236Sken struct mprsas_target *target; 3781265236Sken struct mprsas_lun *lun; 3782265236Sken struct scsi_read_capacity_eedp *rcap_buf; 3783265236Sken 3784265236Sken if (done_ccb == NULL) 3785265236Sken return; 3786265236Sken 3787265236Sken /* Driver need to release devq, it Scsi command is 3788265236Sken * generated by driver internally. 3789265236Sken * Currently there is a single place where driver 3790265236Sken * calls scsi command internally. In future if driver 3791265236Sken * calls more scsi command internally, it needs to release 3792265236Sken * devq internally, since those command will not go back to 3793265236Sken * cam_periph. 3794265236Sken */ 3795265236Sken if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) ) { 3796265236Sken done_ccb->ccb_h.status &= ~CAM_DEV_QFRZN; 3797265236Sken xpt_release_devq(done_ccb->ccb_h.path, 3798265236Sken /*count*/ 1, /*run_queue*/TRUE); 3799265236Sken } 3800283990Sslm 3801265236Sken rcap_buf = (struct scsi_read_capacity_eedp *)done_ccb->csio.data_ptr; 3802265236Sken 3803265236Sken /* 3804265236Sken * Get the LUN ID for the path and look it up in the LUN list for the 3805265236Sken * target. 3806265236Sken */ 3807265236Sken sassc = (struct mprsas_softc *)done_ccb->ccb_h.ppriv_ptr1; 3808299962Sslm KASSERT(done_ccb->ccb_h.target_id < sassc->maxtargets, ("Target %d out " 3809299962Sslm "of bounds in mprsas_read_cap_done\n", done_ccb->ccb_h.target_id)); 3810265236Sken target = &sassc->targets[done_ccb->ccb_h.target_id]; 3811265236Sken SLIST_FOREACH(lun, &target->luns, lun_link) { 3812265236Sken if (lun->lun_id != done_ccb->ccb_h.target_lun) 3813265236Sken continue; 3814265236Sken 3815265236Sken /* 3816265236Sken * Got the LUN in the target's LUN list. Fill it in with EEDP 3817283990Sslm * info. If the READ CAP 16 command had some SCSI error (common 3818265236Sken * if command is not supported), mark the lun as not supporting 3819265236Sken * EEDP and set the block size to 0. 3820265236Sken */ 3821283990Sslm if ((mprsas_get_ccbstatus(done_ccb) != CAM_REQ_CMP) || 3822283990Sslm (done_ccb->csio.scsi_status != SCSI_STATUS_OK)) { 3823265236Sken lun->eedp_formatted = FALSE; 3824265236Sken lun->eedp_block_size = 0; 3825265236Sken break; 3826265236Sken } 3827265236Sken 3828265236Sken if (rcap_buf->protect & 0x01) { 3829283990Sslm mpr_dprint(sassc->sc, MPR_INFO, "LUN %d for target ID " 3830283990Sslm "%d is formatted for EEDP support.\n", 3831283990Sslm done_ccb->ccb_h.target_lun, 3832265236Sken done_ccb->ccb_h.target_id); 3833265236Sken lun->eedp_formatted = TRUE; 3834265236Sken lun->eedp_block_size = scsi_4btoul(rcap_buf->length); 3835265236Sken } 3836265236Sken break; 3837265236Sken } 3838265236Sken 3839265236Sken // Finished with this CCB and path. 3840265236Sken free(rcap_buf, M_MPR); 3841265236Sken xpt_free_path(done_ccb->ccb_h.path); 3842265236Sken xpt_free_ccb(done_ccb); 3843265236Sken} 3844265236Sken#endif /* (__FreeBSD_version < 901503) || \ 3845265236Sken ((__FreeBSD_version >= 1000000) && (__FreeBSD_version < 1000006)) */ 3846265236Sken 3847283990Sslmvoid 3848283990Sslmmprsas_prepare_for_tm(struct mpr_softc *sc, struct mpr_command *tm, 3849283990Sslm struct mprsas_target *target, lun_id_t lun_id) 3850283990Sslm{ 3851283990Sslm union ccb *ccb; 3852283990Sslm path_id_t path_id; 3853283990Sslm 3854283990Sslm /* 3855283990Sslm * Set the INRESET flag for this target so that no I/O will be sent to 3856283990Sslm * the target until the reset has completed. If an I/O request does 3857283990Sslm * happen, the devq will be frozen. The CCB holds the path which is 3858283990Sslm * used to release the devq. The devq is released and the CCB is freed 3859283990Sslm * when the TM completes. 3860283990Sslm */ 3861283990Sslm ccb = xpt_alloc_ccb_nowait(); 3862283990Sslm if (ccb) { 3863283990Sslm path_id = cam_sim_path(sc->sassc->sim); 3864283990Sslm if (xpt_create_path(&ccb->ccb_h.path, xpt_periph, path_id, 3865283990Sslm target->tid, lun_id) != CAM_REQ_CMP) { 3866283990Sslm xpt_free_ccb(ccb); 3867283990Sslm } else { 3868283990Sslm tm->cm_ccb = ccb; 3869283990Sslm tm->cm_targ = target; 3870283990Sslm target->flags |= MPRSAS_TARGET_INRESET; 3871283990Sslm } 3872283990Sslm } 3873283990Sslm} 3874283990Sslm 3875265236Skenint 3876265236Skenmprsas_startup(struct mpr_softc *sc) 3877265236Sken{ 3878265236Sken /* 3879265236Sken * Send the port enable message and set the wait_for_port_enable flag. 3880265236Sken * This flag helps to keep the simq frozen until all discovery events 3881265236Sken * are processed. 3882265236Sken */ 3883265236Sken sc->wait_for_port_enable = 1; 3884265236Sken mprsas_send_portenable(sc); 3885265236Sken return (0); 3886265236Sken} 3887265236Sken 3888265236Skenstatic int 3889265236Skenmprsas_send_portenable(struct mpr_softc *sc) 3890265236Sken{ 3891265236Sken MPI2_PORT_ENABLE_REQUEST *request; 3892265236Sken struct mpr_command *cm; 3893265236Sken 3894265236Sken MPR_FUNCTRACE(sc); 3895265236Sken 3896265236Sken if ((cm = mpr_alloc_command(sc)) == NULL) 3897265236Sken return (EBUSY); 3898265236Sken request = (MPI2_PORT_ENABLE_REQUEST *)cm->cm_req; 3899265236Sken request->Function = MPI2_FUNCTION_PORT_ENABLE; 3900265236Sken request->MsgFlags = 0; 3901265236Sken request->VP_ID = 0; 3902265236Sken cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 3903265236Sken cm->cm_complete = mprsas_portenable_complete; 3904265236Sken cm->cm_data = NULL; 3905265236Sken cm->cm_sge = NULL; 3906265236Sken 3907265236Sken mpr_map_command(sc, cm); 3908265236Sken mpr_dprint(sc, MPR_XINFO, 3909265236Sken "mpr_send_portenable finished cm %p req %p complete %p\n", 3910265236Sken cm, cm->cm_req, cm->cm_complete); 3911265236Sken return (0); 3912265236Sken} 3913265236Sken 3914265236Skenstatic void 3915265236Skenmprsas_portenable_complete(struct mpr_softc *sc, struct mpr_command *cm) 3916265236Sken{ 3917265236Sken MPI2_PORT_ENABLE_REPLY *reply; 3918265236Sken struct mprsas_softc *sassc; 3919265236Sken 3920265236Sken MPR_FUNCTRACE(sc); 3921265236Sken sassc = sc->sassc; 3922265236Sken 3923265236Sken /* 3924265236Sken * Currently there should be no way we can hit this case. It only 3925265236Sken * happens when we have a failure to allocate chain frames, and 3926265236Sken * port enable commands don't have S/G lists. 3927265236Sken */ 3928265236Sken if ((cm->cm_flags & MPR_CM_FLAGS_ERROR_MASK) != 0) { 3929265236Sken mpr_dprint(sc, MPR_ERROR, "%s: cm_flags = %#x for port enable! " 3930265236Sken "This should not happen!\n", __func__, cm->cm_flags); 3931265236Sken } 3932265236Sken 3933265236Sken reply = (MPI2_PORT_ENABLE_REPLY *)cm->cm_reply; 3934265236Sken if (reply == NULL) 3935265236Sken mpr_dprint(sc, MPR_FAULT, "Portenable NULL reply\n"); 3936265236Sken else if (le16toh(reply->IOCStatus & MPI2_IOCSTATUS_MASK) != 3937265236Sken MPI2_IOCSTATUS_SUCCESS) 3938265236Sken mpr_dprint(sc, MPR_FAULT, "Portenable failed\n"); 3939265236Sken 3940265236Sken mpr_free_command(sc, cm); 3941265236Sken if (sc->mpr_ich.ich_arg != NULL) { 3942265236Sken mpr_dprint(sc, MPR_XINFO, "disestablish config intrhook\n"); 3943265236Sken config_intrhook_disestablish(&sc->mpr_ich); 3944265236Sken sc->mpr_ich.ich_arg = NULL; 3945265236Sken } 3946265236Sken 3947265236Sken /* 3948265236Sken * Done waiting for port enable to complete. Decrement the refcount. 3949265236Sken * If refcount is 0, discovery is complete and a rescan of the bus can 3950265236Sken * take place. 3951265236Sken */ 3952265236Sken sc->wait_for_port_enable = 0; 3953265236Sken sc->port_enable_complete = 1; 3954265236Sken wakeup(&sc->port_enable_complete); 3955265236Sken mprsas_startup_decrement(sassc); 3956265236Sken} 3957265236Sken 3958265236Skenint 3959265236Skenmprsas_check_id(struct mprsas_softc *sassc, int id) 3960265236Sken{ 3961265236Sken struct mpr_softc *sc = sassc->sc; 3962265236Sken char *ids; 3963265236Sken char *name; 3964265236Sken 3965265236Sken ids = &sc->exclude_ids[0]; 3966265236Sken while((name = strsep(&ids, ",")) != NULL) { 3967265236Sken if (name[0] == '\0') 3968265236Sken continue; 3969265236Sken if (strtol(name, NULL, 0) == (long)id) 3970265236Sken return (1); 3971265236Sken } 3972265236Sken 3973265236Sken return (0); 3974265236Sken} 3975283990Sslm 3976283990Sslmvoid 3977283990Sslmmprsas_realloc_targets(struct mpr_softc *sc, int maxtargets) 3978283990Sslm{ 3979283990Sslm struct mprsas_softc *sassc; 3980283990Sslm struct mprsas_lun *lun, *lun_tmp; 3981283990Sslm struct mprsas_target *targ; 3982283990Sslm int i; 3983283990Sslm 3984283990Sslm sassc = sc->sassc; 3985283990Sslm /* 3986283990Sslm * The number of targets is based on IOC Facts, so free all of 3987283990Sslm * the allocated LUNs for each target and then the target buffer 3988283990Sslm * itself. 3989283990Sslm */ 3990283990Sslm for (i=0; i< maxtargets; i++) { 3991283990Sslm targ = &sassc->targets[i]; 3992283990Sslm SLIST_FOREACH_SAFE(lun, &targ->luns, lun_link, lun_tmp) { 3993283990Sslm free(lun, M_MPR); 3994283990Sslm } 3995283990Sslm } 3996283990Sslm free(sassc->targets, M_MPR); 3997283990Sslm 3998283990Sslm sassc->targets = malloc(sizeof(struct mprsas_target) * maxtargets, 3999283990Sslm M_MPR, M_WAITOK|M_ZERO); 4000283990Sslm if (!sassc->targets) { 4001283990Sslm panic("%s failed to alloc targets with error %d\n", 4002283990Sslm __func__, ENOMEM); 4003283990Sslm } 4004283990Sslm} 4005