1265236Sken/*- 2265236Sken * Copyright (c) 2009 Yahoo! Inc. 3265236Sken * Copyright (c) 2011-2014 LSI Corp. 4265236Sken * All rights reserved. 5265236Sken * 6265236Sken * Redistribution and use in source and binary forms, with or without 7265236Sken * modification, are permitted provided that the following conditions 8265236Sken * are met: 9265236Sken * 1. Redistributions of source code must retain the above copyright 10265236Sken * notice, this list of conditions and the following disclaimer. 11265236Sken * 2. Redistributions in binary form must reproduce the above copyright 12265236Sken * notice, this list of conditions and the following disclaimer in the 13265236Sken * documentation and/or other materials provided with the distribution. 14265236Sken * 15265236Sken * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16265236Sken * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17265236Sken * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18265236Sken * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19265236Sken * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20265236Sken * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21265236Sken * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22265236Sken * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23265236Sken * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24265236Sken * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25265236Sken * SUCH DAMAGE. 26265236Sken */ 27265236Sken 28265236Sken#include <sys/cdefs.h> 29265236Sken__FBSDID("$FreeBSD$"); 30265236Sken 31265236Sken/* Communications core for LSI MPT2 */ 32265236Sken 33265236Sken/* TODO Move headers to mprvar */ 34265236Sken#include <sys/types.h> 35265236Sken#include <sys/param.h> 36265236Sken#include <sys/systm.h> 37265236Sken#include <sys/kernel.h> 38265236Sken#include <sys/selinfo.h> 39265236Sken#include <sys/module.h> 40265236Sken#include <sys/bus.h> 41265236Sken#include <sys/conf.h> 42265236Sken#include <sys/bio.h> 43265236Sken#include <sys/malloc.h> 44265236Sken#include <sys/uio.h> 45265236Sken#include <sys/sysctl.h> 46265236Sken#include <sys/endian.h> 47265236Sken#include <sys/queue.h> 48265236Sken#include <sys/kthread.h> 49265236Sken#include <sys/taskqueue.h> 50265236Sken#include <sys/sbuf.h> 51265236Sken 52265236Sken#include <machine/bus.h> 53265236Sken#include <machine/resource.h> 54265236Sken#include <sys/rman.h> 55265236Sken 56265236Sken#include <machine/stdarg.h> 57265236Sken 58265236Sken#include <cam/cam.h> 59265236Sken#include <cam/cam_ccb.h> 60265236Sken#include <cam/cam_debug.h> 61265236Sken#include <cam/cam_sim.h> 62265236Sken#include <cam/cam_xpt_sim.h> 63265236Sken#include <cam/cam_xpt_periph.h> 64265236Sken#include <cam/cam_periph.h> 65265236Sken#include <cam/scsi/scsi_all.h> 66265236Sken#include <cam/scsi/scsi_message.h> 67265236Sken#if __FreeBSD_version >= 900026 68265236Sken#include <cam/scsi/smp_all.h> 69265236Sken#endif 70265236Sken 71265236Sken#include <dev/mpr/mpi/mpi2_type.h> 72265236Sken#include <dev/mpr/mpi/mpi2.h> 73265236Sken#include <dev/mpr/mpi/mpi2_ioc.h> 74265236Sken#include <dev/mpr/mpi/mpi2_sas.h> 75265236Sken#include <dev/mpr/mpi/mpi2_cnfg.h> 76265236Sken#include <dev/mpr/mpi/mpi2_init.h> 77265236Sken#include <dev/mpr/mpi/mpi2_tool.h> 78265236Sken#include <dev/mpr/mpr_ioctl.h> 79265236Sken#include <dev/mpr/mprvar.h> 80265236Sken#include <dev/mpr/mpr_table.h> 81265236Sken#include <dev/mpr/mpr_sas.h> 82265236Sken 83265236Sken#define MPRSAS_DISCOVERY_TIMEOUT 20 84265236Sken#define MPRSAS_MAX_DISCOVERY_TIMEOUTS 10 /* 200 seconds */ 85265236Sken 86265236Sken/* 87265236Sken * static array to check SCSI OpCode for EEDP protection bits 88265236Sken */ 89265236Sken#define PRO_R MPI2_SCSIIO_EEDPFLAGS_CHECK_REMOVE_OP 90265236Sken#define PRO_W MPI2_SCSIIO_EEDPFLAGS_INSERT_OP 91265236Sken#define PRO_V MPI2_SCSIIO_EEDPFLAGS_INSERT_OP 92265236Skenstatic uint8_t op_code_prot[256] = { 93265236Sken 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 94265236Sken 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 95265236Sken 0, 0, 0, 0, 0, 0, 0, 0, PRO_R, 0, PRO_W, 0, 0, 0, PRO_W, PRO_V, 96265236Sken 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 97265236Sken 0, PRO_W, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 98265236Sken 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 99265236Sken 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, PRO_R, 0, PRO_W, 0, 0, 0, PRO_W, PRO_V, 102265236Sken 0, 0, 0, PRO_W, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 103265236Sken 0, 0, 0, 0, 0, 0, 0, 0, PRO_R, 0, PRO_W, 0, 0, 0, PRO_W, PRO_V, 104265236Sken 0, 0, 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, 0, 0, 0, 0, 0, 0, 0, 0 109265236Sken}; 110265236Sken 111265236SkenMALLOC_DEFINE(M_MPRSAS, "MPRSAS", "MPR SAS memory"); 112265236Sken 113265236Skenstatic void mprsas_remove_device(struct mpr_softc *, struct mpr_command *); 114265236Skenstatic void mprsas_remove_complete(struct mpr_softc *, struct mpr_command *); 115265236Skenstatic void mprsas_action(struct cam_sim *sim, union ccb *ccb); 116265236Skenstatic void mprsas_poll(struct cam_sim *sim); 117265236Skenstatic void mprsas_scsiio_timeout(void *data); 118265236Skenstatic void mprsas_abort_complete(struct mpr_softc *sc, 119265236Sken struct mpr_command *cm); 120265236Skenstatic void mprsas_action_scsiio(struct mprsas_softc *, union ccb *); 121265236Skenstatic void mprsas_scsiio_complete(struct mpr_softc *, struct mpr_command *); 122265236Skenstatic void mprsas_action_resetdev(struct mprsas_softc *, union ccb *); 123265236Skenstatic void mprsas_resetdev_complete(struct mpr_softc *, 124265236Sken struct mpr_command *); 125265236Skenstatic int mprsas_send_abort(struct mpr_softc *sc, struct mpr_command *tm, 126265236Sken struct mpr_command *cm); 127265236Skenstatic int mprsas_send_reset(struct mpr_softc *sc, struct mpr_command *tm, 128265236Sken uint8_t type); 129265236Skenstatic void mprsas_async(void *callback_arg, uint32_t code, 130265236Sken struct cam_path *path, void *arg); 131265236Skenstatic void mprsas_prepare_ssu(struct mpr_softc *sc, struct cam_path *path, 132265236Sken struct ccb_getdev *cgd); 133265236Sken#if (__FreeBSD_version < 901503) || \ 134265236Sken ((__FreeBSD_version >= 1000000) && (__FreeBSD_version < 1000006)) 135265236Skenstatic void mprsas_check_eedp(struct mpr_softc *sc, struct cam_path *path, 136265236Sken struct ccb_getdev *cgd); 137265236Skenstatic void mprsas_read_cap_done(struct cam_periph *periph, 138265236Sken union ccb *done_ccb); 139265236Sken#endif 140265236Skenstatic int mprsas_send_portenable(struct mpr_softc *sc); 141265236Skenstatic void mprsas_portenable_complete(struct mpr_softc *sc, 142265236Sken struct mpr_command *cm); 143265236Sken 144265236Sken#if __FreeBSD_version >= 900026 145265236Skenstatic void 146265236Skenmprsas_smpio_complete(struct mpr_softc *sc, struct mpr_command *cm); 147265236Skenstatic void mprsas_send_smpcmd(struct mprsas_softc *sassc, 148265236Sken union ccb *ccb, uint64_t sasaddr); 149265236Skenstatic void 150265236Skenmprsas_action_smpio(struct mprsas_softc *sassc, union ccb *ccb); 151265236Sken#endif 152265236Sken 153265236Skenstruct mprsas_target * 154265236Skenmprsas_find_target_by_handle(struct mprsas_softc *sassc, int start, 155265236Sken uint16_t handle) 156265236Sken{ 157265236Sken struct mprsas_target *target; 158265236Sken int i; 159265236Sken 160265236Sken for (i = start; i < sassc->maxtargets; i++) { 161265236Sken target = &sassc->targets[i]; 162265236Sken if (target->handle == handle) 163265236Sken return (target); 164265236Sken } 165265236Sken 166265236Sken return (NULL); 167265236Sken} 168265236Sken 169265236Sken/* we need to freeze the simq during attach and diag reset, to avoid failing 170265236Sken * commands before device handles have been found by discovery. Since 171265236Sken * discovery involves reading config pages and possibly sending commands, 172265236Sken * discovery actions may continue even after we receive the end of discovery 173265236Sken * event, so refcount discovery actions instead of assuming we can unfreeze 174265236Sken * the simq when we get the event. 175265236Sken */ 176265236Skenvoid 177265236Skenmprsas_startup_increment(struct mprsas_softc *sassc) 178265236Sken{ 179265236Sken MPR_FUNCTRACE(sassc->sc); 180265236Sken 181265236Sken if ((sassc->flags & MPRSAS_IN_STARTUP) != 0) { 182265236Sken if (sassc->startup_refcount++ == 0) { 183265236Sken /* just starting, freeze the simq */ 184265236Sken mpr_dprint(sassc->sc, MPR_INIT, 185265236Sken "%s freezing simq\n", __func__); 186266549Sken#if (__FreeBSD_version >= 1000039) || \ 187266549Sken ((__FreeBSD_version < 1000000) && (__FreeBSD_version >= 902502)) 188265236Sken xpt_hold_boot(); 189265236Sken#endif 190265236Sken xpt_freeze_simq(sassc->sim, 1); 191265236Sken } 192265236Sken mpr_dprint(sassc->sc, MPR_INIT, "%s refcount %u\n", __func__, 193265236Sken sassc->startup_refcount); 194265236Sken } 195265236Sken} 196265236Sken 197265236Skenvoid 198265236Skenmprsas_release_simq_reinit(struct mprsas_softc *sassc) 199265236Sken{ 200265236Sken if (sassc->flags & MPRSAS_QUEUE_FROZEN) { 201265236Sken sassc->flags &= ~MPRSAS_QUEUE_FROZEN; 202265236Sken xpt_release_simq(sassc->sim, 1); 203265236Sken mpr_dprint(sassc->sc, MPR_INFO, "Unfreezing SIM queue\n"); 204265236Sken } 205265236Sken} 206265236Sken 207265236Skenvoid 208265236Skenmprsas_startup_decrement(struct mprsas_softc *sassc) 209265236Sken{ 210265236Sken MPR_FUNCTRACE(sassc->sc); 211265236Sken 212265236Sken if ((sassc->flags & MPRSAS_IN_STARTUP) != 0) { 213265236Sken if (--sassc->startup_refcount == 0) { 214265236Sken /* finished all discovery-related actions, release 215265236Sken * the simq and rescan for the latest topology. 216265236Sken */ 217265236Sken mpr_dprint(sassc->sc, MPR_INIT, 218265236Sken "%s releasing simq\n", __func__); 219265236Sken sassc->flags &= ~MPRSAS_IN_STARTUP; 220265236Sken xpt_release_simq(sassc->sim, 1); 221266549Sken#if (__FreeBSD_version >= 1000039) || \ 222266549Sken ((__FreeBSD_version < 1000000) && (__FreeBSD_version >= 902502)) 223265236Sken xpt_release_boot(); 224265236Sken#else 225265236Sken mprsas_rescan_target(sassc->sc, NULL); 226265236Sken#endif 227265236Sken } 228265236Sken mpr_dprint(sassc->sc, MPR_INIT, "%s refcount %u\n", __func__, 229265236Sken sassc->startup_refcount); 230265236Sken } 231265236Sken} 232265236Sken 233265236Sken/* LSI's firmware requires us to stop sending commands when we're doing task 234265236Sken * management, so refcount the TMs and keep the simq frozen when any are in 235265236Sken * use. 236265236Sken */ 237265236Skenstruct mpr_command * 238265236Skenmprsas_alloc_tm(struct mpr_softc *sc) 239265236Sken{ 240265236Sken struct mpr_command *tm; 241265236Sken 242265236Sken MPR_FUNCTRACE(sc); 243265236Sken tm = mpr_alloc_high_priority_command(sc); 244265236Sken if (tm != NULL) { 245265236Sken if (sc->sassc->tm_count++ == 0) { 246265236Sken mpr_dprint(sc, MPR_RECOVERY, 247265236Sken "%s freezing simq\n", __func__); 248265236Sken xpt_freeze_simq(sc->sassc->sim, 1); 249265236Sken } 250265236Sken mpr_dprint(sc, MPR_RECOVERY, "%s tm_count %u\n", __func__, 251265236Sken sc->sassc->tm_count); 252265236Sken } 253265236Sken return tm; 254265236Sken} 255265236Sken 256265236Skenvoid 257265236Skenmprsas_free_tm(struct mpr_softc *sc, struct mpr_command *tm) 258265236Sken{ 259265236Sken mpr_dprint(sc, MPR_TRACE, "%s", __func__); 260265236Sken if (tm == NULL) 261265236Sken return; 262265236Sken 263265236Sken /* if there are no TMs in use, we can release the simq. We use our 264265236Sken * own refcount so that it's easier for a diag reset to cleanup and 265265236Sken * release the simq. 266265236Sken */ 267265236Sken if (--sc->sassc->tm_count == 0) { 268265236Sken mpr_dprint(sc, MPR_RECOVERY, "%s releasing simq\n", __func__); 269265236Sken xpt_release_simq(sc->sassc->sim, 1); 270265236Sken } 271265236Sken mpr_dprint(sc, MPR_RECOVERY, "%s tm_count %u\n", __func__, 272265236Sken sc->sassc->tm_count); 273265236Sken 274265236Sken mpr_free_high_priority_command(sc, tm); 275265236Sken} 276265236Sken 277265236Skenvoid 278265236Skenmprsas_rescan_target(struct mpr_softc *sc, struct mprsas_target *targ) 279265236Sken{ 280265236Sken struct mprsas_softc *sassc = sc->sassc; 281265236Sken path_id_t pathid; 282265236Sken target_id_t targetid; 283265236Sken union ccb *ccb; 284265236Sken 285265236Sken MPR_FUNCTRACE(sc); 286265236Sken pathid = cam_sim_path(sassc->sim); 287265236Sken if (targ == NULL) 288265236Sken targetid = CAM_TARGET_WILDCARD; 289265236Sken else 290265236Sken targetid = targ - sassc->targets; 291265236Sken 292265236Sken /* 293265236Sken * Allocate a CCB and schedule a rescan. 294265236Sken */ 295265236Sken ccb = xpt_alloc_ccb_nowait(); 296265236Sken if (ccb == NULL) { 297265236Sken mpr_dprint(sc, MPR_ERROR, "unable to alloc CCB for rescan\n"); 298265236Sken return; 299265236Sken } 300265236Sken 301265236Sken if (xpt_create_path(&ccb->ccb_h.path, NULL, pathid, 302265236Sken targetid, CAM_LUN_WILDCARD) != CAM_REQ_CMP) { 303265236Sken mpr_dprint(sc, MPR_ERROR, "unable to create path for rescan\n"); 304265236Sken xpt_free_ccb(ccb); 305265236Sken return; 306265236Sken } 307265236Sken 308265236Sken if (targetid == CAM_TARGET_WILDCARD) 309265236Sken ccb->ccb_h.func_code = XPT_SCAN_BUS; 310265236Sken else 311265236Sken ccb->ccb_h.func_code = XPT_SCAN_TGT; 312265236Sken 313265236Sken mpr_dprint(sc, MPR_TRACE, "%s targetid %u\n", __func__, targetid); 314265236Sken xpt_rescan(ccb); 315265236Sken} 316265236Sken 317265236Skenstatic void 318265236Skenmprsas_log_command(struct mpr_command *cm, u_int level, const char *fmt, ...) 319265236Sken{ 320265236Sken struct sbuf sb; 321265236Sken va_list ap; 322265236Sken char str[192]; 323265236Sken char path_str[64]; 324265236Sken 325265236Sken if (cm == NULL) 326265236Sken return; 327265236Sken 328265236Sken /* No need to be in here if debugging isn't enabled */ 329265236Sken if ((cm->cm_sc->mpr_debug & level) == 0) 330265236Sken return; 331265236Sken 332265236Sken sbuf_new(&sb, str, sizeof(str), 0); 333265236Sken 334265236Sken va_start(ap, fmt); 335265236Sken 336265236Sken if (cm->cm_ccb != NULL) { 337265236Sken xpt_path_string(cm->cm_ccb->csio.ccb_h.path, path_str, 338265236Sken sizeof(path_str)); 339265236Sken sbuf_cat(&sb, path_str); 340265236Sken if (cm->cm_ccb->ccb_h.func_code == XPT_SCSI_IO) { 341265236Sken scsi_command_string(&cm->cm_ccb->csio, &sb); 342265236Sken sbuf_printf(&sb, "length %d ", 343265236Sken cm->cm_ccb->csio.dxfer_len); 344265236Sken } 345265236Sken } else { 346265236Sken sbuf_printf(&sb, "(noperiph:%s%d:%u:%u:%u): ", 347265236Sken cam_sim_name(cm->cm_sc->sassc->sim), 348265236Sken cam_sim_unit(cm->cm_sc->sassc->sim), 349265236Sken cam_sim_bus(cm->cm_sc->sassc->sim), 350265236Sken cm->cm_targ ? cm->cm_targ->tid : 0xFFFFFFFF, 351265236Sken cm->cm_lun); 352265236Sken } 353265236Sken 354265236Sken sbuf_printf(&sb, "SMID %u ", cm->cm_desc.Default.SMID); 355265236Sken sbuf_vprintf(&sb, fmt, ap); 356265236Sken sbuf_finish(&sb); 357265236Sken mpr_dprint_field(cm->cm_sc, level, "%s", sbuf_data(&sb)); 358265236Sken 359265236Sken va_end(ap); 360265236Sken} 361265236Sken 362265236Skenstatic void 363265236Skenmprsas_remove_volume(struct mpr_softc *sc, struct mpr_command *tm) 364265236Sken{ 365265236Sken MPI2_SCSI_TASK_MANAGE_REPLY *reply; 366265236Sken struct mprsas_target *targ; 367265236Sken uint16_t handle; 368265236Sken 369265236Sken MPR_FUNCTRACE(sc); 370265236Sken 371265236Sken reply = (MPI2_SCSI_TASK_MANAGE_REPLY *)tm->cm_reply; 372265236Sken handle = (uint16_t)(uintptr_t)tm->cm_complete_data; 373265236Sken targ = tm->cm_targ; 374265236Sken 375265236Sken if (reply == NULL) { 376265236Sken /* XXX retry the remove after the diag reset completes? */ 377265236Sken mpr_dprint(sc, MPR_FAULT, "%s NULL reply resetting device " 378265236Sken "0x%04x\n", __func__, handle); 379265236Sken mprsas_free_tm(sc, tm); 380265236Sken return; 381265236Sken } 382265236Sken 383265236Sken if (reply->IOCStatus != MPI2_IOCSTATUS_SUCCESS) { 384265236Sken mpr_dprint(sc, MPR_FAULT, "IOCStatus = 0x%x while resetting " 385265236Sken "device 0x%x\n", reply->IOCStatus, handle); 386265236Sken mprsas_free_tm(sc, tm); 387265236Sken return; 388265236Sken } 389265236Sken 390265236Sken mpr_dprint(sc, MPR_XINFO, "Reset aborted %u commands\n", 391265236Sken reply->TerminationCount); 392265236Sken mpr_free_reply(sc, tm->cm_reply_data); 393265236Sken tm->cm_reply = NULL; /* Ensures the reply won't get re-freed */ 394265236Sken 395265236Sken mpr_dprint(sc, MPR_XINFO, "clearing target %u handle 0x%04x\n", 396265236Sken targ->tid, handle); 397265236Sken 398265236Sken /* 399265236Sken * Don't clear target if remove fails because things will get confusing. 400265236Sken * Leave the devname and sasaddr intact so that we know to avoid reusing 401265236Sken * this target id if possible, and so we can assign the same target id 402265236Sken * to this device if it comes back in the future. 403265236Sken */ 404265236Sken if (reply->IOCStatus == MPI2_IOCSTATUS_SUCCESS) { 405265236Sken targ = tm->cm_targ; 406265236Sken targ->handle = 0x0; 407265236Sken targ->encl_handle = 0x0; 408265236Sken targ->encl_level_valid = 0x0; 409265236Sken targ->encl_level = 0x0; 410265236Sken targ->connector_name[0] = ' '; 411265236Sken targ->connector_name[1] = ' '; 412265236Sken targ->connector_name[2] = ' '; 413265236Sken targ->connector_name[3] = ' '; 414265236Sken targ->encl_slot = 0x0; 415265236Sken targ->exp_dev_handle = 0x0; 416265236Sken targ->phy_num = 0x0; 417265236Sken targ->linkrate = 0x0; 418265236Sken targ->devinfo = 0x0; 419265236Sken targ->flags = 0x0; 420265236Sken targ->scsi_req_desc_type = 0; 421265236Sken } 422265236Sken 423265236Sken mprsas_free_tm(sc, tm); 424265236Sken} 425265236Sken 426265236Sken 427265236Sken/* 428265236Sken * No Need to call "MPI2_SAS_OP_REMOVE_DEVICE" For Volume removal. 429265236Sken * Otherwise Volume Delete is same as Bare Drive Removal. 430265236Sken */ 431265236Skenvoid 432265236Skenmprsas_prepare_volume_remove(struct mprsas_softc *sassc, uint16_t handle) 433265236Sken{ 434265236Sken MPI2_SCSI_TASK_MANAGE_REQUEST *req; 435265236Sken struct mpr_softc *sc; 436265236Sken struct mpr_command *cm; 437265236Sken struct mprsas_target *targ = NULL; 438265236Sken 439265236Sken MPR_FUNCTRACE(sassc->sc); 440265236Sken sc = sassc->sc; 441265236Sken 442265236Sken targ = mprsas_find_target_by_handle(sassc, 0, handle); 443265236Sken if (targ == NULL) { 444265236Sken /* FIXME: what is the action? */ 445265236Sken /* We don't know about this device? */ 446265236Sken mpr_dprint(sc, MPR_ERROR, 447265236Sken "%s %d : invalid handle 0x%x \n", __func__,__LINE__, handle); 448265236Sken return; 449265236Sken } 450265236Sken 451265236Sken targ->flags |= MPRSAS_TARGET_INREMOVAL; 452265236Sken 453265236Sken cm = mprsas_alloc_tm(sc); 454265236Sken if (cm == NULL) { 455265236Sken mpr_dprint(sc, MPR_ERROR, 456265236Sken "%s: command alloc failure\n", __func__); 457265236Sken return; 458265236Sken } 459265236Sken 460265236Sken mprsas_rescan_target(sc, targ); 461265236Sken 462265236Sken req = (MPI2_SCSI_TASK_MANAGE_REQUEST *)cm->cm_req; 463265236Sken req->DevHandle = targ->handle; 464265236Sken req->Function = MPI2_FUNCTION_SCSI_TASK_MGMT; 465265236Sken req->TaskType = MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET; 466265236Sken 467265236Sken /* SAS Hard Link Reset / SATA Link Reset */ 468265236Sken req->MsgFlags = MPI2_SCSITASKMGMT_MSGFLAGS_LINK_RESET; 469265236Sken 470265236Sken cm->cm_targ = targ; 471265236Sken cm->cm_data = NULL; 472265236Sken cm->cm_desc.HighPriority.RequestFlags = 473265236Sken MPI2_REQ_DESCRIPT_FLAGS_HIGH_PRIORITY; 474265236Sken cm->cm_complete = mprsas_remove_volume; 475265236Sken cm->cm_complete_data = (void *)(uintptr_t)handle; 476265236Sken mpr_map_command(sc, cm); 477265236Sken} 478265236Sken 479265236Sken/* 480265236Sken * The MPT2 firmware performs debounce on the link to avoid transient link 481265236Sken * errors and false removals. When it does decide that link has been lost 482265236Sken * and a device needs to go away, it expects that the host will perform a 483265236Sken * target reset and then an op remove. The reset has the side-effect of 484265236Sken * aborting any outstanding requests for the device, which is required for 485265236Sken * the op-remove to succeed. It's not clear if the host should check for 486265236Sken * the device coming back alive after the reset. 487265236Sken */ 488265236Skenvoid 489265236Skenmprsas_prepare_remove(struct mprsas_softc *sassc, uint16_t handle) 490265236Sken{ 491265236Sken MPI2_SCSI_TASK_MANAGE_REQUEST *req; 492265236Sken struct mpr_softc *sc; 493265236Sken struct mpr_command *cm; 494265236Sken struct mprsas_target *targ = NULL; 495265236Sken 496265236Sken MPR_FUNCTRACE(sassc->sc); 497265236Sken 498265236Sken sc = sassc->sc; 499265236Sken 500265236Sken targ = mprsas_find_target_by_handle(sassc, 0, handle); 501265236Sken if (targ == NULL) { 502265236Sken /* FIXME: what is the action? */ 503265236Sken /* We don't know about this device? */ 504265236Sken mpr_dprint(sc, MPR_ERROR, "%s : invalid handle 0x%x \n", 505265236Sken __func__, handle); 506265236Sken return; 507265236Sken } 508265236Sken 509265236Sken targ->flags |= MPRSAS_TARGET_INREMOVAL; 510265236Sken 511265236Sken cm = mprsas_alloc_tm(sc); 512265236Sken if (cm == NULL) { 513265236Sken mpr_dprint(sc, MPR_ERROR, "%s: command alloc failure\n", 514265236Sken __func__); 515265236Sken return; 516265236Sken } 517265236Sken 518265236Sken mprsas_rescan_target(sc, targ); 519265236Sken 520265236Sken req = (MPI2_SCSI_TASK_MANAGE_REQUEST *)cm->cm_req; 521265236Sken memset(req, 0, sizeof(*req)); 522265236Sken req->DevHandle = htole16(targ->handle); 523265236Sken req->Function = MPI2_FUNCTION_SCSI_TASK_MGMT; 524265236Sken req->TaskType = MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET; 525265236Sken 526265236Sken /* SAS Hard Link Reset / SATA Link Reset */ 527265236Sken req->MsgFlags = MPI2_SCSITASKMGMT_MSGFLAGS_LINK_RESET; 528265236Sken 529265236Sken cm->cm_targ = targ; 530265236Sken cm->cm_data = NULL; 531265236Sken cm->cm_desc.HighPriority.RequestFlags = 532265236Sken MPI2_REQ_DESCRIPT_FLAGS_HIGH_PRIORITY; 533265236Sken cm->cm_complete = mprsas_remove_device; 534265236Sken cm->cm_complete_data = (void *)(uintptr_t)handle; 535265236Sken mpr_map_command(sc, cm); 536265236Sken} 537265236Sken 538265236Skenstatic void 539265236Skenmprsas_remove_device(struct mpr_softc *sc, struct mpr_command *tm) 540265236Sken{ 541265236Sken MPI2_SCSI_TASK_MANAGE_REPLY *reply; 542265236Sken MPI2_SAS_IOUNIT_CONTROL_REQUEST *req; 543265236Sken struct mprsas_target *targ; 544265236Sken struct mpr_command *next_cm; 545265236Sken uint16_t handle; 546265236Sken 547265236Sken MPR_FUNCTRACE(sc); 548265236Sken 549265236Sken reply = (MPI2_SCSI_TASK_MANAGE_REPLY *)tm->cm_reply; 550265236Sken handle = (uint16_t)(uintptr_t)tm->cm_complete_data; 551265236Sken targ = tm->cm_targ; 552265236Sken 553265236Sken /* 554265236Sken * Currently there should be no way we can hit this case. It only 555265236Sken * happens when we have a failure to allocate chain frames, and 556265236Sken * task management commands don't have S/G lists. 557265236Sken */ 558265236Sken if ((tm->cm_flags & MPR_CM_FLAGS_ERROR_MASK) != 0) { 559265236Sken mpr_dprint(sc, MPR_ERROR, "%s: cm_flags = %#x for remove of " 560265236Sken "handle %#04x! This should not happen!\n", __func__, 561265236Sken tm->cm_flags, handle); 562265236Sken mprsas_free_tm(sc, tm); 563265236Sken return; 564265236Sken } 565265236Sken 566265236Sken if (reply == NULL) { 567265236Sken /* XXX retry the remove after the diag reset completes? */ 568265236Sken mpr_dprint(sc, MPR_FAULT, "%s NULL reply resetting device " 569265236Sken "0x%04x\n", __func__, handle); 570265236Sken mprsas_free_tm(sc, tm); 571265236Sken return; 572265236Sken } 573265236Sken 574265236Sken if (le16toh(reply->IOCStatus) != MPI2_IOCSTATUS_SUCCESS) { 575265236Sken mpr_dprint(sc, MPR_FAULT, "IOCStatus = 0x%x while resetting " 576265236Sken "device 0x%x\n", le16toh(reply->IOCStatus), handle); 577265236Sken mprsas_free_tm(sc, tm); 578265236Sken return; 579265236Sken } 580265236Sken 581265236Sken mpr_dprint(sc, MPR_XINFO, "Reset aborted %u commands\n", 582265236Sken le32toh(reply->TerminationCount)); 583265236Sken mpr_free_reply(sc, tm->cm_reply_data); 584265236Sken tm->cm_reply = NULL; /* Ensures the reply won't get re-freed */ 585265236Sken 586265236Sken /* Reuse the existing command */ 587265236Sken req = (MPI2_SAS_IOUNIT_CONTROL_REQUEST *)tm->cm_req; 588265236Sken memset(req, 0, sizeof(*req)); 589265236Sken req->Function = MPI2_FUNCTION_SAS_IO_UNIT_CONTROL; 590265236Sken req->Operation = MPI2_SAS_OP_REMOVE_DEVICE; 591265236Sken req->DevHandle = htole16(handle); 592265236Sken tm->cm_data = NULL; 593265236Sken tm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 594265236Sken tm->cm_complete = mprsas_remove_complete; 595265236Sken tm->cm_complete_data = (void *)(uintptr_t)handle; 596265236Sken 597265236Sken mpr_map_command(sc, tm); 598265236Sken 599265236Sken mpr_dprint(sc, MPR_XINFO, "clearing target %u handle 0x%04x\n", 600265236Sken targ->tid, handle); 601265236Sken if (targ->encl_level_valid) { 602265236Sken mpr_dprint(sc, MPR_XINFO, "At enclosure level %d, slot %d, " 603265236Sken "connector name (%4s)\n", targ->encl_level, targ->encl_slot, 604265236Sken targ->connector_name); 605265236Sken } 606265236Sken TAILQ_FOREACH_SAFE(tm, &targ->commands, cm_link, next_cm) { 607265236Sken union ccb *ccb; 608265236Sken 609265236Sken mpr_dprint(sc, MPR_XINFO, "Completing missed command %p\n", tm); 610265236Sken ccb = tm->cm_complete_data; 611265236Sken ccb->ccb_h.status = CAM_DEV_NOT_THERE; 612265236Sken mprsas_scsiio_complete(sc, tm); 613265236Sken } 614265236Sken} 615265236Sken 616265236Skenstatic void 617265236Skenmprsas_remove_complete(struct mpr_softc *sc, struct mpr_command *tm) 618265236Sken{ 619265236Sken MPI2_SAS_IOUNIT_CONTROL_REPLY *reply; 620265236Sken uint16_t handle; 621265236Sken struct mprsas_target *targ; 622265236Sken struct mprsas_lun *lun; 623265236Sken 624265236Sken MPR_FUNCTRACE(sc); 625265236Sken 626265236Sken reply = (MPI2_SAS_IOUNIT_CONTROL_REPLY *)tm->cm_reply; 627265236Sken handle = (uint16_t)(uintptr_t)tm->cm_complete_data; 628265236Sken 629265236Sken /* 630265236Sken * Currently there should be no way we can hit this case. It only 631265236Sken * happens when we have a failure to allocate chain frames, and 632265236Sken * task management commands don't have S/G lists. 633265236Sken */ 634265236Sken if ((tm->cm_flags & MPR_CM_FLAGS_ERROR_MASK) != 0) { 635265236Sken mpr_dprint(sc, MPR_XINFO, "%s: cm_flags = %#x for remove of " 636265236Sken "handle %#04x! This should not happen!\n", __func__, 637265236Sken tm->cm_flags, handle); 638265236Sken mprsas_free_tm(sc, tm); 639265236Sken return; 640265236Sken } 641265236Sken 642265236Sken if (reply == NULL) { 643265236Sken /* most likely a chip reset */ 644265236Sken mpr_dprint(sc, MPR_FAULT, "%s NULL reply removing device " 645265236Sken "0x%04x\n", __func__, handle); 646265236Sken mprsas_free_tm(sc, tm); 647265236Sken return; 648265236Sken } 649265236Sken 650265236Sken mpr_dprint(sc, MPR_XINFO, "%s on handle 0x%04x, IOCStatus= 0x%x\n", 651265236Sken __func__, handle, le16toh(reply->IOCStatus)); 652265236Sken 653265236Sken /* 654265236Sken * Don't clear target if remove fails because things will get confusing. 655265236Sken * Leave the devname and sasaddr intact so that we know to avoid reusing 656265236Sken * this target id if possible, and so we can assign the same target id 657265236Sken * to this device if it comes back in the future. 658265236Sken */ 659265236Sken if (le16toh(reply->IOCStatus) == MPI2_IOCSTATUS_SUCCESS) { 660265236Sken targ = tm->cm_targ; 661265236Sken targ->handle = 0x0; 662265236Sken targ->encl_handle = 0x0; 663265236Sken targ->encl_level_valid = 0x0; 664265236Sken targ->encl_level = 0x0; 665265236Sken targ->connector_name[0] = ' '; 666265236Sken targ->connector_name[1] = ' '; 667265236Sken targ->connector_name[2] = ' '; 668265236Sken targ->connector_name[3] = ' '; 669265236Sken targ->encl_slot = 0x0; 670265236Sken targ->exp_dev_handle = 0x0; 671265236Sken targ->phy_num = 0x0; 672265236Sken targ->linkrate = 0x0; 673265236Sken targ->devinfo = 0x0; 674265236Sken targ->flags = 0x0; 675265236Sken targ->scsi_req_desc_type = 0; 676265236Sken 677265236Sken while (!SLIST_EMPTY(&targ->luns)) { 678265236Sken lun = SLIST_FIRST(&targ->luns); 679265236Sken SLIST_REMOVE_HEAD(&targ->luns, lun_link); 680265236Sken free(lun, M_MPR); 681265236Sken } 682265236Sken } 683265236Sken 684265236Sken mprsas_free_tm(sc, tm); 685265236Sken} 686265236Sken 687265236Skenstatic int 688265236Skenmprsas_register_events(struct mpr_softc *sc) 689265236Sken{ 690265236Sken uint8_t events[16]; 691265236Sken 692265236Sken bzero(events, 16); 693265236Sken setbit(events, MPI2_EVENT_SAS_DEVICE_STATUS_CHANGE); 694265236Sken setbit(events, MPI2_EVENT_SAS_DISCOVERY); 695265236Sken setbit(events, MPI2_EVENT_SAS_BROADCAST_PRIMITIVE); 696265236Sken setbit(events, MPI2_EVENT_SAS_INIT_DEVICE_STATUS_CHANGE); 697265236Sken setbit(events, MPI2_EVENT_SAS_INIT_TABLE_OVERFLOW); 698265236Sken setbit(events, MPI2_EVENT_SAS_TOPOLOGY_CHANGE_LIST); 699265236Sken setbit(events, MPI2_EVENT_SAS_ENCL_DEVICE_STATUS_CHANGE); 700265236Sken setbit(events, MPI2_EVENT_IR_CONFIGURATION_CHANGE_LIST); 701265236Sken setbit(events, MPI2_EVENT_IR_VOLUME); 702265236Sken setbit(events, MPI2_EVENT_IR_PHYSICAL_DISK); 703265236Sken setbit(events, MPI2_EVENT_IR_OPERATION_STATUS); 704265236Sken setbit(events, MPI2_EVENT_TEMP_THRESHOLD); 705265236Sken 706265236Sken mpr_register_events(sc, events, mprsas_evt_handler, NULL, 707265236Sken &sc->sassc->mprsas_eh); 708265236Sken 709265236Sken return (0); 710265236Sken} 711265236Sken 712265236Skenint 713265236Skenmpr_attach_sas(struct mpr_softc *sc) 714265236Sken{ 715265236Sken struct mprsas_softc *sassc; 716265236Sken cam_status status; 717265236Sken int unit, error = 0; 718265236Sken 719265236Sken MPR_FUNCTRACE(sc); 720265236Sken 721265236Sken sassc = malloc(sizeof(struct mprsas_softc), M_MPR, M_WAITOK|M_ZERO); 722265236Sken if (!sassc) { 723265236Sken device_printf(sc->mpr_dev, "Cannot allocate memory %s %d\n", 724265236Sken __func__, __LINE__); 725265236Sken return (ENOMEM); 726265236Sken } 727265236Sken 728265236Sken /* 729265236Sken * XXX MaxTargets could change during a reinit. since we don't 730265236Sken * resize the targets[] array during such an event, cache the value 731265236Sken * of MaxTargets here so that we don't get into trouble later. This 732265236Sken * should move into the reinit logic. 733265236Sken */ 734265236Sken sassc->maxtargets = sc->facts->MaxTargets; 735265236Sken sassc->targets = malloc(sizeof(struct mprsas_target) * 736265236Sken sassc->maxtargets, M_MPR, M_WAITOK|M_ZERO); 737265236Sken if (!sassc->targets) { 738265236Sken device_printf(sc->mpr_dev, "Cannot allocate memory %s %d\n", 739265236Sken __func__, __LINE__); 740265236Sken free(sassc, M_MPR); 741265236Sken return (ENOMEM); 742265236Sken } 743265236Sken sc->sassc = sassc; 744265236Sken sassc->sc = sc; 745265236Sken 746265236Sken if ((sassc->devq = cam_simq_alloc(sc->num_reqs)) == NULL) { 747265236Sken mpr_dprint(sc, MPR_ERROR, "Cannot allocate SIMQ\n"); 748265236Sken error = ENOMEM; 749265236Sken goto out; 750265236Sken } 751265236Sken 752265236Sken unit = device_get_unit(sc->mpr_dev); 753265236Sken sassc->sim = cam_sim_alloc(mprsas_action, mprsas_poll, "mpr", sassc, 754265236Sken unit, &sc->mpr_mtx, sc->num_reqs, sc->num_reqs, sassc->devq); 755265236Sken if (sassc->sim == NULL) { 756265236Sken mpr_dprint(sc, MPR_ERROR, "Cannot allocate SIM\n"); 757265236Sken error = EINVAL; 758265236Sken goto out; 759265236Sken } 760265236Sken 761265236Sken TAILQ_INIT(&sassc->ev_queue); 762265236Sken 763265236Sken /* Initialize taskqueue for Event Handling */ 764265236Sken TASK_INIT(&sassc->ev_task, 0, mprsas_firmware_event_work, sc); 765265236Sken sassc->ev_tq = taskqueue_create("mpr_taskq", M_NOWAIT | M_ZERO, 766265236Sken taskqueue_thread_enqueue, &sassc->ev_tq); 767265236Sken 768265236Sken /* Run the task queue with lowest priority */ 769265236Sken taskqueue_start_threads(&sassc->ev_tq, 1, 255, "%s taskq", 770265236Sken device_get_nameunit(sc->mpr_dev)); 771265236Sken 772265236Sken mpr_lock(sc); 773265236Sken 774265236Sken /* 775265236Sken * XXX There should be a bus for every port on the adapter, but since 776265236Sken * we're just going to fake the topology for now, we'll pretend that 777265236Sken * everything is just a target on a single bus. 778265236Sken */ 779265236Sken if ((error = xpt_bus_register(sassc->sim, sc->mpr_dev, 0)) != 0) { 780265236Sken mpr_dprint(sc, MPR_ERROR, "Error %d registering SCSI bus\n", 781265236Sken error); 782265236Sken mpr_unlock(sc); 783265236Sken goto out; 784265236Sken } 785265236Sken 786265236Sken /* 787265236Sken * Assume that discovery events will start right away. Freezing 788265236Sken * 789265236Sken * Hold off boot until discovery is complete. 790265236Sken */ 791265236Sken sassc->flags |= MPRSAS_IN_STARTUP | MPRSAS_IN_DISCOVERY; 792265236Sken sc->sassc->startup_refcount = 0; 793265236Sken mprsas_startup_increment(sassc); 794265236Sken 795265236Sken callout_init(&sassc->discovery_callout, 1 /*mprafe*/); 796265236Sken 797265236Sken sassc->tm_count = 0; 798265236Sken 799265236Sken /* 800265236Sken * Register for async events so we can determine the EEDP 801265236Sken * capabilities of devices. 802265236Sken */ 803265236Sken status = xpt_create_path(&sassc->path, /*periph*/NULL, 804265236Sken cam_sim_path(sc->sassc->sim), CAM_TARGET_WILDCARD, 805265236Sken CAM_LUN_WILDCARD); 806265236Sken if (status != CAM_REQ_CMP) { 807265236Sken mpr_printf(sc, "Error %#x creating sim path\n", status); 808265236Sken sassc->path = NULL; 809265236Sken } else { 810265236Sken int event; 811265236Sken 812265236Sken#if (__FreeBSD_version >= 1000006) || \ 813265236Sken ((__FreeBSD_version >= 901503) && (__FreeBSD_version < 1000000)) 814265236Sken event = AC_ADVINFO_CHANGED | AC_FOUND_DEVICE; 815265236Sken#else 816265236Sken event = AC_FOUND_DEVICE; 817265236Sken#endif 818265729Sken 819265729Sken /* 820265729Sken * Prior to the CAM locking improvements, we can't call 821265729Sken * xpt_register_async() with a particular path specified. 822265729Sken * 823265729Sken * If a path isn't specified, xpt_register_async() will 824265729Sken * generate a wildcard path and acquire the XPT lock while 825265729Sken * it calls xpt_action() to execute the XPT_SASYNC_CB CCB. 826265729Sken * It will then drop the XPT lock once that is done. 827265729Sken * 828265729Sken * If a path is specified for xpt_register_async(), it will 829265729Sken * not acquire and drop the XPT lock around the call to 830265729Sken * xpt_action(). xpt_action() asserts that the caller 831265729Sken * holds the SIM lock, so the SIM lock has to be held when 832265729Sken * calling xpt_register_async() when the path is specified. 833265729Sken * 834265729Sken * But xpt_register_async calls xpt_for_all_devices(), 835265729Sken * which calls xptbustraverse(), which will acquire each 836265729Sken * SIM lock. When it traverses our particular bus, it will 837265729Sken * necessarily acquire the SIM lock, which will lead to a 838265729Sken * recursive lock acquisition. 839265729Sken * 840265729Sken * The CAM locking changes fix this problem by acquiring 841265729Sken * the XPT topology lock around bus traversal in 842265729Sken * xptbustraverse(), so the caller can hold the SIM lock 843265729Sken * and it does not cause a recursive lock acquisition. 844265729Sken * 845265729Sken * These __FreeBSD_version values are approximate, especially 846265729Sken * for stable/10, which is two months later than the actual 847265729Sken * change. 848265729Sken */ 849265729Sken 850265729Sken#if (__FreeBSD_version < 1000703) || \ 851265729Sken ((__FreeBSD_version >= 1100000) && (__FreeBSD_version < 1100002)) 852265729Sken mpr_unlock(sc); 853265236Sken status = xpt_register_async(event, mprsas_async, sc, 854265729Sken NULL); 855265729Sken mpr_lock(sc); 856265729Sken#else 857265729Sken status = xpt_register_async(event, mprsas_async, sc, 858265236Sken sassc->path); 859265729Sken#endif 860265729Sken 861265236Sken if (status != CAM_REQ_CMP) { 862265236Sken mpr_dprint(sc, MPR_ERROR, 863265236Sken "Error %#x registering async handler for " 864265236Sken "AC_ADVINFO_CHANGED events\n", status); 865265236Sken xpt_free_path(sassc->path); 866265236Sken sassc->path = NULL; 867265236Sken } 868265236Sken } 869265236Sken if (status != CAM_REQ_CMP) { 870265236Sken /* 871265236Sken * EEDP use is the exception, not the rule. 872265236Sken * Warn the user, but do not fail to attach. 873265236Sken */ 874265236Sken mpr_printf(sc, "EEDP capabilities disabled.\n"); 875265236Sken } 876265236Sken 877265236Sken mpr_unlock(sc); 878265236Sken 879265236Sken mprsas_register_events(sc); 880265236Skenout: 881265236Sken if (error) 882265236Sken mpr_detach_sas(sc); 883265236Sken return (error); 884265236Sken} 885265236Sken 886265236Skenint 887265236Skenmpr_detach_sas(struct mpr_softc *sc) 888265236Sken{ 889265236Sken struct mprsas_softc *sassc; 890265236Sken struct mprsas_lun *lun, *lun_tmp; 891265236Sken struct mprsas_target *targ; 892265236Sken int i; 893265236Sken 894265236Sken MPR_FUNCTRACE(sc); 895265236Sken 896265236Sken if (sc->sassc == NULL) 897265236Sken return (0); 898265236Sken 899265236Sken sassc = sc->sassc; 900265236Sken mpr_deregister_events(sc, sassc->mprsas_eh); 901265236Sken 902265236Sken /* 903265236Sken * Drain and free the event handling taskqueue with the lock 904265236Sken * unheld so that any parallel processing tasks drain properly 905265236Sken * without deadlocking. 906265236Sken */ 907265236Sken if (sassc->ev_tq != NULL) 908265236Sken taskqueue_free(sassc->ev_tq); 909265236Sken 910265236Sken /* Make sure CAM doesn't wedge if we had to bail out early. */ 911265236Sken mpr_lock(sc); 912265236Sken 913265236Sken /* Deregister our async handler */ 914265236Sken if (sassc->path != NULL) { 915265236Sken xpt_register_async(0, mprsas_async, sc, sassc->path); 916265236Sken xpt_free_path(sassc->path); 917265236Sken sassc->path = NULL; 918265236Sken } 919265236Sken 920265236Sken if (sassc->flags & MPRSAS_IN_STARTUP) 921265236Sken xpt_release_simq(sassc->sim, 1); 922265236Sken 923265236Sken if (sassc->sim != NULL) { 924265236Sken xpt_bus_deregister(cam_sim_path(sassc->sim)); 925265236Sken cam_sim_free(sassc->sim, FALSE); 926265236Sken } 927265236Sken 928265236Sken sassc->flags |= MPRSAS_SHUTDOWN; 929265236Sken mpr_unlock(sc); 930265236Sken 931265236Sken if (sassc->devq != NULL) 932265236Sken cam_simq_free(sassc->devq); 933265236Sken 934265236Sken for (i = 0; i < sassc->maxtargets; i++) { 935265236Sken targ = &sassc->targets[i]; 936265236Sken SLIST_FOREACH_SAFE(lun, &targ->luns, lun_link, lun_tmp) { 937265236Sken free(lun, M_MPR); 938265236Sken } 939265236Sken } 940265236Sken free(sassc->targets, M_MPR); 941265236Sken free(sassc, M_MPR); 942265236Sken sc->sassc = NULL; 943265236Sken 944265236Sken return (0); 945265236Sken} 946265236Sken 947265236Skenvoid 948265236Skenmprsas_discovery_end(struct mprsas_softc *sassc) 949265236Sken{ 950265236Sken struct mpr_softc *sc = sassc->sc; 951265236Sken 952265236Sken MPR_FUNCTRACE(sc); 953265236Sken 954265236Sken if (sassc->flags & MPRSAS_DISCOVERY_TIMEOUT_PENDING) 955265236Sken callout_stop(&sassc->discovery_callout); 956265236Sken 957265236Sken} 958265236Sken 959265236Skenstatic void 960265236Skenmprsas_action(struct cam_sim *sim, union ccb *ccb) 961265236Sken{ 962265236Sken struct mprsas_softc *sassc; 963265236Sken 964265236Sken sassc = cam_sim_softc(sim); 965265236Sken 966265236Sken MPR_FUNCTRACE(sassc->sc); 967265236Sken mpr_dprint(sassc->sc, MPR_TRACE, "%s func 0x%x\n", __func__, 968265236Sken ccb->ccb_h.func_code); 969265236Sken mtx_assert(&sassc->sc->mpr_mtx, MA_OWNED); 970265236Sken 971265236Sken switch (ccb->ccb_h.func_code) { 972265236Sken case XPT_PATH_INQ: 973265236Sken { 974265236Sken struct ccb_pathinq *cpi = &ccb->cpi; 975265236Sken 976265236Sken cpi->version_num = 1; 977265236Sken cpi->hba_inquiry = PI_SDTR_ABLE|PI_TAG_ABLE|PI_WIDE_16; 978265236Sken cpi->target_sprt = 0; 979266549Sken#if (__FreeBSD_version >= 1000039) || \ 980266549Sken ((__FreeBSD_version < 1000000) && (__FreeBSD_version >= 902502)) 981265236Sken cpi->hba_misc = PIM_NOBUSRESET | PIM_UNMAPPED | PIM_NOSCAN; 982265236Sken#else 983265236Sken cpi->hba_misc = PIM_NOBUSRESET | PIM_UNMAPPED; 984265236Sken#endif 985265236Sken cpi->hba_eng_cnt = 0; 986265236Sken cpi->max_target = sassc->maxtargets - 1; 987265236Sken cpi->max_lun = 255; 988265236Sken cpi->initiator_id = sassc->maxtargets - 1; 989265236Sken strncpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN); 990265236Sken strncpy(cpi->hba_vid, "LSILogic", HBA_IDLEN); 991265236Sken strncpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN); 992265236Sken cpi->unit_number = cam_sim_unit(sim); 993265236Sken cpi->bus_id = cam_sim_bus(sim); 994265236Sken /* 995265236Sken * XXXSLM-I think this needs to change based on config page or 996265236Sken * something instead of hardcoded to 150000. 997265236Sken */ 998265236Sken cpi->base_transfer_speed = 150000; 999265236Sken cpi->transport = XPORT_SAS; 1000265236Sken cpi->transport_version = 0; 1001265236Sken cpi->protocol = PROTO_SCSI; 1002265236Sken cpi->protocol_version = SCSI_REV_SPC; 1003265236Sken#if __FreeBSD_version >= 800001 1004265236Sken /* 1005265236Sken * XXXSLM-probably need to base this number on max SGL's and 1006265236Sken * page size. 1007265236Sken */ 1008265236Sken cpi->maxio = 256 * 1024; 1009265236Sken#endif 1010265236Sken cpi->ccb_h.status = CAM_REQ_CMP; 1011265236Sken break; 1012265236Sken } 1013265236Sken case XPT_GET_TRAN_SETTINGS: 1014265236Sken { 1015265236Sken struct ccb_trans_settings *cts; 1016265236Sken struct ccb_trans_settings_sas *sas; 1017265236Sken struct ccb_trans_settings_scsi *scsi; 1018265236Sken struct mprsas_target *targ; 1019265236Sken 1020265236Sken cts = &ccb->cts; 1021265236Sken sas = &cts->xport_specific.sas; 1022265236Sken scsi = &cts->proto_specific.scsi; 1023265236Sken 1024265236Sken KASSERT(cts->ccb_h.target_id < sassc->maxtargets, 1025265236Sken ("Target %d out of bounds in XPT_GET_TRAN_SETTINGS\n", 1026265236Sken cts->ccb_h.target_id)); 1027265236Sken targ = &sassc->targets[cts->ccb_h.target_id]; 1028265236Sken if (targ->handle == 0x0) { 1029265236Sken cts->ccb_h.status = CAM_DEV_NOT_THERE; 1030265236Sken break; 1031265236Sken } 1032265236Sken 1033265236Sken cts->protocol_version = SCSI_REV_SPC2; 1034265236Sken cts->transport = XPORT_SAS; 1035265236Sken cts->transport_version = 0; 1036265236Sken 1037265236Sken sas->valid = CTS_SAS_VALID_SPEED; 1038265236Sken switch (targ->linkrate) { 1039265236Sken case 0x08: 1040265236Sken sas->bitrate = 150000; 1041265236Sken break; 1042265236Sken case 0x09: 1043265236Sken sas->bitrate = 300000; 1044265236Sken break; 1045265236Sken case 0x0a: 1046265236Sken sas->bitrate = 600000; 1047265236Sken break; 1048265236Sken default: 1049265236Sken sas->valid = 0; 1050265236Sken } 1051265236Sken 1052265236Sken cts->protocol = PROTO_SCSI; 1053265236Sken scsi->valid = CTS_SCSI_VALID_TQ; 1054265236Sken scsi->flags = CTS_SCSI_FLAGS_TAG_ENB; 1055265236Sken 1056265236Sken cts->ccb_h.status = CAM_REQ_CMP; 1057265236Sken break; 1058265236Sken } 1059265236Sken case XPT_CALC_GEOMETRY: 1060265236Sken cam_calc_geometry(&ccb->ccg, /*extended*/1); 1061265236Sken ccb->ccb_h.status = CAM_REQ_CMP; 1062265236Sken break; 1063265236Sken case XPT_RESET_DEV: 1064265236Sken mpr_dprint(sassc->sc, MPR_XINFO, 1065265236Sken "mprsas_action XPT_RESET_DEV\n"); 1066265236Sken mprsas_action_resetdev(sassc, ccb); 1067265236Sken return; 1068265236Sken case XPT_RESET_BUS: 1069265236Sken case XPT_ABORT: 1070265236Sken case XPT_TERM_IO: 1071265236Sken mpr_dprint(sassc->sc, MPR_XINFO, 1072265236Sken "mprsas_action faking success for abort or reset\n"); 1073265236Sken ccb->ccb_h.status = CAM_REQ_CMP; 1074265236Sken break; 1075265236Sken case XPT_SCSI_IO: 1076265236Sken mprsas_action_scsiio(sassc, ccb); 1077265236Sken return; 1078265236Sken#if __FreeBSD_version >= 900026 1079265236Sken case XPT_SMP_IO: 1080265236Sken mprsas_action_smpio(sassc, ccb); 1081265236Sken return; 1082265236Sken#endif 1083265236Sken default: 1084265236Sken ccb->ccb_h.status = CAM_FUNC_NOTAVAIL; 1085265236Sken break; 1086265236Sken } 1087265236Sken xpt_done(ccb); 1088265236Sken 1089265236Sken} 1090265236Sken 1091265236Skenstatic void 1092265236Skenmprsas_announce_reset(struct mpr_softc *sc, uint32_t ac_code, 1093265236Sken target_id_t target_id, lun_id_t lun_id) 1094265236Sken{ 1095265236Sken path_id_t path_id = cam_sim_path(sc->sassc->sim); 1096265236Sken struct cam_path *path; 1097265236Sken 1098265236Sken mpr_dprint(sc, MPR_XINFO, "%s code %x target %d lun %jx\n", __func__, 1099265236Sken ac_code, target_id, (uintmax_t)lun_id); 1100265236Sken 1101265236Sken if (xpt_create_path(&path, NULL, 1102265236Sken path_id, target_id, lun_id) != CAM_REQ_CMP) { 1103265236Sken mpr_dprint(sc, MPR_ERROR, "unable to create path for reset " 1104265236Sken "notification\n"); 1105265236Sken return; 1106265236Sken } 1107265236Sken 1108265236Sken xpt_async(ac_code, path, NULL); 1109265236Sken xpt_free_path(path); 1110265236Sken} 1111265236Sken 1112265236Skenstatic void 1113265236Skenmprsas_complete_all_commands(struct mpr_softc *sc) 1114265236Sken{ 1115265236Sken struct mpr_command *cm; 1116265236Sken int i; 1117265236Sken int completed; 1118265236Sken 1119265236Sken MPR_FUNCTRACE(sc); 1120265236Sken mtx_assert(&sc->mpr_mtx, MA_OWNED); 1121265236Sken 1122265236Sken /* complete all commands with a NULL reply */ 1123265236Sken for (i = 1; i < sc->num_reqs; i++) { 1124265236Sken cm = &sc->commands[i]; 1125265236Sken cm->cm_reply = NULL; 1126265236Sken completed = 0; 1127265236Sken 1128265236Sken if (cm->cm_flags & MPR_CM_FLAGS_POLLED) 1129265236Sken cm->cm_flags |= MPR_CM_FLAGS_COMPLETE; 1130265236Sken 1131265236Sken if (cm->cm_complete != NULL) { 1132265236Sken mprsas_log_command(cm, MPR_RECOVERY, 1133265236Sken "completing cm %p state %x ccb %p for diag reset\n", 1134265236Sken cm, cm->cm_state, cm->cm_ccb); 1135265236Sken cm->cm_complete(sc, cm); 1136265236Sken completed = 1; 1137265236Sken } 1138265236Sken 1139265236Sken if (cm->cm_flags & MPR_CM_FLAGS_WAKEUP) { 1140265236Sken mprsas_log_command(cm, MPR_RECOVERY, 1141265236Sken "waking up cm %p state %x ccb %p for diag reset\n", 1142265236Sken cm, cm->cm_state, cm->cm_ccb); 1143265236Sken wakeup(cm); 1144265236Sken completed = 1; 1145265236Sken } 1146265236Sken 1147265236Sken if ((completed == 0) && (cm->cm_state != MPR_CM_STATE_FREE)) { 1148265236Sken /* this should never happen, but if it does, log */ 1149265236Sken mprsas_log_command(cm, MPR_RECOVERY, 1150265236Sken "cm %p state %x flags 0x%x ccb %p during diag " 1151265236Sken "reset\n", cm, cm->cm_state, cm->cm_flags, 1152265236Sken cm->cm_ccb); 1153265236Sken } 1154265236Sken } 1155265236Sken} 1156265236Sken 1157265236Skenvoid 1158265236Skenmprsas_handle_reinit(struct mpr_softc *sc) 1159265236Sken{ 1160265236Sken int i; 1161265236Sken 1162265236Sken /* Go back into startup mode and freeze the simq, so that CAM 1163265236Sken * doesn't send any commands until after we've rediscovered all 1164265236Sken * targets and found the proper device handles for them. 1165265236Sken * 1166265236Sken * After the reset, portenable will trigger discovery, and after all 1167265236Sken * discovery-related activities have finished, the simq will be 1168265236Sken * released. 1169265236Sken */ 1170265236Sken mpr_dprint(sc, MPR_INIT, "%s startup\n", __func__); 1171265236Sken sc->sassc->flags |= MPRSAS_IN_STARTUP; 1172265236Sken sc->sassc->flags |= MPRSAS_IN_DISCOVERY; 1173265236Sken mprsas_startup_increment(sc->sassc); 1174265236Sken 1175265236Sken /* notify CAM of a bus reset */ 1176265236Sken mprsas_announce_reset(sc, AC_BUS_RESET, CAM_TARGET_WILDCARD, 1177265236Sken CAM_LUN_WILDCARD); 1178265236Sken 1179265236Sken /* complete and cleanup after all outstanding commands */ 1180265236Sken mprsas_complete_all_commands(sc); 1181265236Sken 1182265236Sken mpr_dprint(sc, MPR_INIT, "%s startup %u tm %u after command " 1183265236Sken "completion\n", __func__, sc->sassc->startup_refcount, 1184265236Sken sc->sassc->tm_count); 1185265236Sken 1186265236Sken /* zero all the target handles, since they may change after the 1187265236Sken * reset, and we have to rediscover all the targets and use the new 1188265236Sken * handles. 1189265236Sken */ 1190265236Sken for (i = 0; i < sc->sassc->maxtargets; i++) { 1191265236Sken if (sc->sassc->targets[i].outstanding != 0) 1192265236Sken mpr_dprint(sc, MPR_INIT, "target %u outstanding %u\n", 1193265236Sken i, sc->sassc->targets[i].outstanding); 1194265236Sken sc->sassc->targets[i].handle = 0x0; 1195265236Sken sc->sassc->targets[i].exp_dev_handle = 0x0; 1196265236Sken sc->sassc->targets[i].outstanding = 0; 1197265236Sken sc->sassc->targets[i].flags = MPRSAS_TARGET_INDIAGRESET; 1198265236Sken } 1199265236Sken} 1200265236Skenstatic void 1201265236Skenmprsas_tm_timeout(void *data) 1202265236Sken{ 1203265236Sken struct mpr_command *tm = data; 1204265236Sken struct mpr_softc *sc = tm->cm_sc; 1205265236Sken 1206265236Sken mtx_assert(&sc->mpr_mtx, MA_OWNED); 1207265236Sken 1208265236Sken mprsas_log_command(tm, MPR_INFO|MPR_RECOVERY, 1209265236Sken "task mgmt %p timed out\n", tm); 1210265236Sken mpr_reinit(sc); 1211265236Sken} 1212265236Sken 1213265236Skenstatic void 1214265236Skenmprsas_logical_unit_reset_complete(struct mpr_softc *sc, 1215265236Sken struct mpr_command *tm) 1216265236Sken{ 1217265236Sken MPI2_SCSI_TASK_MANAGE_REPLY *reply; 1218265236Sken MPI2_SCSI_TASK_MANAGE_REQUEST *req; 1219265236Sken unsigned int cm_count = 0; 1220265236Sken struct mpr_command *cm; 1221265236Sken struct mprsas_target *targ; 1222265236Sken 1223265236Sken callout_stop(&tm->cm_callout); 1224265236Sken 1225265236Sken req = (MPI2_SCSI_TASK_MANAGE_REQUEST *)tm->cm_req; 1226265236Sken reply = (MPI2_SCSI_TASK_MANAGE_REPLY *)tm->cm_reply; 1227265236Sken targ = tm->cm_targ; 1228265236Sken 1229265236Sken /* 1230265236Sken * Currently there should be no way we can hit this case. It only 1231265236Sken * happens when we have a failure to allocate chain frames, and 1232265236Sken * task management commands don't have S/G lists. 1233265236Sken */ 1234265236Sken if ((tm->cm_flags & MPR_CM_FLAGS_ERROR_MASK) != 0) { 1235265236Sken mpr_dprint(sc, MPR_ERROR, "%s: cm_flags = %#x for LUN reset! " 1236265236Sken "This should not happen!\n", __func__, tm->cm_flags); 1237265236Sken mprsas_free_tm(sc, tm); 1238265236Sken return; 1239265236Sken } 1240265236Sken 1241265236Sken if (reply == NULL) { 1242265236Sken mprsas_log_command(tm, MPR_RECOVERY, 1243265236Sken "NULL reset reply for tm %p\n", tm); 1244265236Sken if ((sc->mpr_flags & MPR_FLAGS_DIAGRESET) != 0) { 1245265236Sken /* this completion was due to a reset, just cleanup */ 1246265236Sken targ->flags &= ~MPRSAS_TARGET_INRESET; 1247265236Sken targ->tm = NULL; 1248265236Sken mprsas_free_tm(sc, tm); 1249265236Sken } 1250265236Sken else { 1251265236Sken /* we should have gotten a reply. */ 1252265236Sken mpr_reinit(sc); 1253265236Sken } 1254265236Sken return; 1255265236Sken } 1256265236Sken 1257265236Sken mprsas_log_command(tm, MPR_RECOVERY, 1258265236Sken "logical unit reset status 0x%x code 0x%x count %u\n", 1259265236Sken le16toh(reply->IOCStatus), le32toh(reply->ResponseCode), 1260265236Sken le32toh(reply->TerminationCount)); 1261265236Sken 1262265236Sken /* See if there are any outstanding commands for this LUN. 1263265236Sken * This could be made more efficient by using a per-LU data 1264265236Sken * structure of some sort. 1265265236Sken */ 1266265236Sken TAILQ_FOREACH(cm, &targ->commands, cm_link) { 1267265236Sken if (cm->cm_lun == tm->cm_lun) 1268265236Sken cm_count++; 1269265236Sken } 1270265236Sken 1271265236Sken if (cm_count == 0) { 1272265236Sken mprsas_log_command(tm, MPR_RECOVERY|MPR_INFO, 1273265236Sken "logical unit %u finished recovery after reset\n", 1274265236Sken tm->cm_lun, tm); 1275265236Sken 1276265236Sken mprsas_announce_reset(sc, AC_SENT_BDR, tm->cm_targ->tid, 1277265236Sken tm->cm_lun); 1278265236Sken 1279265236Sken /* we've finished recovery for this logical unit. check and 1280265236Sken * see if some other logical unit has a timedout command 1281265236Sken * that needs to be processed. 1282265236Sken */ 1283265236Sken cm = TAILQ_FIRST(&targ->timedout_commands); 1284265236Sken if (cm) { 1285265236Sken mprsas_send_abort(sc, tm, cm); 1286265236Sken } 1287265236Sken else { 1288265236Sken targ->tm = NULL; 1289265236Sken mprsas_free_tm(sc, tm); 1290265236Sken } 1291265236Sken } 1292265236Sken else { 1293265236Sken /* if we still have commands for this LUN, the reset 1294265236Sken * effectively failed, regardless of the status reported. 1295265236Sken * Escalate to a target reset. 1296265236Sken */ 1297265236Sken mprsas_log_command(tm, MPR_RECOVERY, 1298265236Sken "logical unit reset complete for tm %p, but still have %u " 1299265236Sken "command(s)\n", tm, cm_count); 1300265236Sken mprsas_send_reset(sc, tm, 1301265236Sken MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET); 1302265236Sken } 1303265236Sken} 1304265236Sken 1305265236Skenstatic void 1306265236Skenmprsas_target_reset_complete(struct mpr_softc *sc, struct mpr_command *tm) 1307265236Sken{ 1308265236Sken MPI2_SCSI_TASK_MANAGE_REPLY *reply; 1309265236Sken MPI2_SCSI_TASK_MANAGE_REQUEST *req; 1310265236Sken struct mprsas_target *targ; 1311265236Sken 1312265236Sken callout_stop(&tm->cm_callout); 1313265236Sken 1314265236Sken req = (MPI2_SCSI_TASK_MANAGE_REQUEST *)tm->cm_req; 1315265236Sken reply = (MPI2_SCSI_TASK_MANAGE_REPLY *)tm->cm_reply; 1316265236Sken targ = tm->cm_targ; 1317265236Sken 1318265236Sken /* 1319265236Sken * Currently there should be no way we can hit this case. It only 1320265236Sken * happens when we have a failure to allocate chain frames, and 1321265236Sken * task management commands don't have S/G lists. 1322265236Sken */ 1323265236Sken if ((tm->cm_flags & MPR_CM_FLAGS_ERROR_MASK) != 0) { 1324265236Sken mpr_dprint(sc, MPR_ERROR,"%s: cm_flags = %#x for target reset! " 1325265236Sken "This should not happen!\n", __func__, tm->cm_flags); 1326265236Sken mprsas_free_tm(sc, tm); 1327265236Sken return; 1328265236Sken } 1329265236Sken 1330265236Sken if (reply == NULL) { 1331265236Sken mprsas_log_command(tm, MPR_RECOVERY, 1332265236Sken "NULL reset reply for tm %p\n", tm); 1333265236Sken if ((sc->mpr_flags & MPR_FLAGS_DIAGRESET) != 0) { 1334265236Sken /* this completion was due to a reset, just cleanup */ 1335265236Sken targ->flags &= ~MPRSAS_TARGET_INRESET; 1336265236Sken targ->tm = NULL; 1337265236Sken mprsas_free_tm(sc, tm); 1338265236Sken } 1339265236Sken else { 1340265236Sken /* we should have gotten a reply. */ 1341265236Sken mpr_reinit(sc); 1342265236Sken } 1343265236Sken return; 1344265236Sken } 1345265236Sken 1346265236Sken mprsas_log_command(tm, MPR_RECOVERY, 1347265236Sken "target reset status 0x%x code 0x%x count %u\n", 1348265236Sken le16toh(reply->IOCStatus), le32toh(reply->ResponseCode), 1349265236Sken le32toh(reply->TerminationCount)); 1350265236Sken 1351265236Sken targ->flags &= ~MPRSAS_TARGET_INRESET; 1352265236Sken 1353265236Sken if (targ->outstanding == 0) { 1354265236Sken /* we've finished recovery for this target and all 1355265236Sken * of its logical units. 1356265236Sken */ 1357265236Sken mprsas_log_command(tm, MPR_RECOVERY|MPR_INFO, 1358265236Sken "recovery finished after target reset\n"); 1359265236Sken 1360265236Sken mprsas_announce_reset(sc, AC_SENT_BDR, tm->cm_targ->tid, 1361265236Sken CAM_LUN_WILDCARD); 1362265236Sken 1363265236Sken targ->tm = NULL; 1364265236Sken mprsas_free_tm(sc, tm); 1365265236Sken } 1366265236Sken else { 1367265236Sken /* after a target reset, if this target still has 1368265236Sken * outstanding commands, the reset effectively failed, 1369265236Sken * regardless of the status reported. escalate. 1370265236Sken */ 1371265236Sken mprsas_log_command(tm, MPR_RECOVERY, 1372265236Sken "target reset complete for tm %p, but still have %u " 1373265236Sken "command(s)\n", tm, targ->outstanding); 1374265236Sken mpr_reinit(sc); 1375265236Sken } 1376265236Sken} 1377265236Sken 1378265236Sken#define MPR_RESET_TIMEOUT 30 1379265236Sken 1380265236Skenstatic int 1381265236Skenmprsas_send_reset(struct mpr_softc *sc, struct mpr_command *tm, uint8_t type) 1382265236Sken{ 1383265236Sken MPI2_SCSI_TASK_MANAGE_REQUEST *req; 1384265236Sken struct mprsas_target *target; 1385265236Sken int err; 1386265236Sken 1387265236Sken target = tm->cm_targ; 1388265236Sken if (target->handle == 0) { 1389265236Sken mpr_dprint(sc, MPR_ERROR,"%s null devhandle for target_id %d\n", 1390265236Sken __func__, target->tid); 1391265236Sken return -1; 1392265236Sken } 1393265236Sken 1394265236Sken req = (MPI2_SCSI_TASK_MANAGE_REQUEST *)tm->cm_req; 1395265236Sken req->DevHandle = htole16(target->handle); 1396265236Sken req->Function = MPI2_FUNCTION_SCSI_TASK_MGMT; 1397265236Sken req->TaskType = type; 1398265236Sken 1399265236Sken if (type == MPI2_SCSITASKMGMT_TASKTYPE_LOGICAL_UNIT_RESET) { 1400265236Sken /* XXX Need to handle invalid LUNs */ 1401265236Sken MPR_SET_LUN(req->LUN, tm->cm_lun); 1402265236Sken tm->cm_targ->logical_unit_resets++; 1403265236Sken mprsas_log_command(tm, MPR_RECOVERY|MPR_INFO, 1404265236Sken "sending logical unit reset\n"); 1405265236Sken tm->cm_complete = mprsas_logical_unit_reset_complete; 1406265236Sken } 1407265236Sken else if (type == MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET) { 1408265236Sken /* 1409265236Sken * Target reset method = 1410265236Sken * SAS Hard Link Reset / SATA Link Reset 1411265236Sken */ 1412265236Sken req->MsgFlags = MPI2_SCSITASKMGMT_MSGFLAGS_LINK_RESET; 1413265236Sken tm->cm_targ->target_resets++; 1414265236Sken tm->cm_targ->flags |= MPRSAS_TARGET_INRESET; 1415265236Sken mprsas_log_command(tm, MPR_RECOVERY|MPR_INFO, 1416265236Sken "sending target reset\n"); 1417265236Sken tm->cm_complete = mprsas_target_reset_complete; 1418265236Sken } 1419265236Sken else { 1420265236Sken mpr_dprint(sc, MPR_ERROR, "unexpected reset type 0x%x\n", type); 1421265236Sken return -1; 1422265236Sken } 1423265236Sken 1424265236Sken mpr_dprint(sc, MPR_XINFO, "to target %u handle 0x%04x\n", target->tid, 1425265236Sken target->handle); 1426265236Sken if (target->encl_level_valid) { 1427265236Sken mpr_dprint(sc, MPR_XINFO, "At enclosure level %d, slot %d, " 1428265236Sken "connector name (%4s)\n", target->encl_level, 1429265236Sken target->encl_slot, target->connector_name); 1430265236Sken } 1431265236Sken 1432265236Sken tm->cm_data = NULL; 1433265236Sken tm->cm_desc.HighPriority.RequestFlags = 1434265236Sken MPI2_REQ_DESCRIPT_FLAGS_HIGH_PRIORITY; 1435265236Sken tm->cm_complete_data = (void *)tm; 1436265236Sken 1437265236Sken callout_reset(&tm->cm_callout, MPR_RESET_TIMEOUT * hz, 1438265236Sken mprsas_tm_timeout, tm); 1439265236Sken 1440265236Sken err = mpr_map_command(sc, tm); 1441265236Sken if (err) 1442265236Sken mprsas_log_command(tm, MPR_RECOVERY, 1443265236Sken "error %d sending reset type %u\n", 1444265236Sken err, type); 1445265236Sken 1446265236Sken return err; 1447265236Sken} 1448265236Sken 1449265236Sken 1450265236Skenstatic void 1451265236Skenmprsas_abort_complete(struct mpr_softc *sc, struct mpr_command *tm) 1452265236Sken{ 1453265236Sken struct mpr_command *cm; 1454265236Sken MPI2_SCSI_TASK_MANAGE_REPLY *reply; 1455265236Sken MPI2_SCSI_TASK_MANAGE_REQUEST *req; 1456265236Sken struct mprsas_target *targ; 1457265236Sken 1458265236Sken callout_stop(&tm->cm_callout); 1459265236Sken 1460265236Sken req = (MPI2_SCSI_TASK_MANAGE_REQUEST *)tm->cm_req; 1461265236Sken reply = (MPI2_SCSI_TASK_MANAGE_REPLY *)tm->cm_reply; 1462265236Sken targ = tm->cm_targ; 1463265236Sken 1464265236Sken /* 1465265236Sken * Currently there should be no way we can hit this case. It only 1466265236Sken * happens when we have a failure to allocate chain frames, and 1467265236Sken * task management commands don't have S/G lists. 1468265236Sken */ 1469265236Sken if ((tm->cm_flags & MPR_CM_FLAGS_ERROR_MASK) != 0) { 1470265236Sken mprsas_log_command(tm, MPR_RECOVERY, 1471265236Sken "cm_flags = %#x for abort %p TaskMID %u!\n", 1472265236Sken tm->cm_flags, tm, le16toh(req->TaskMID)); 1473265236Sken mprsas_free_tm(sc, tm); 1474265236Sken return; 1475265236Sken } 1476265236Sken 1477265236Sken if (reply == NULL) { 1478265236Sken mprsas_log_command(tm, MPR_RECOVERY, 1479265236Sken "NULL abort reply for tm %p TaskMID %u\n", 1480265236Sken tm, le16toh(req->TaskMID)); 1481265236Sken if ((sc->mpr_flags & MPR_FLAGS_DIAGRESET) != 0) { 1482265236Sken /* this completion was due to a reset, just cleanup */ 1483265236Sken targ->tm = NULL; 1484265236Sken mprsas_free_tm(sc, tm); 1485265236Sken } 1486265236Sken else { 1487265236Sken /* we should have gotten a reply. */ 1488265236Sken mpr_reinit(sc); 1489265236Sken } 1490265236Sken return; 1491265236Sken } 1492265236Sken 1493265236Sken mprsas_log_command(tm, MPR_RECOVERY, 1494265236Sken "abort TaskMID %u status 0x%x code 0x%x count %u\n", 1495265236Sken le16toh(req->TaskMID), 1496265236Sken le16toh(reply->IOCStatus), le32toh(reply->ResponseCode), 1497265236Sken le32toh(reply->TerminationCount)); 1498265236Sken 1499265236Sken cm = TAILQ_FIRST(&tm->cm_targ->timedout_commands); 1500265236Sken if (cm == NULL) { 1501265236Sken /* if there are no more timedout commands, we're done with 1502265236Sken * error recovery for this target. 1503265236Sken */ 1504265236Sken mprsas_log_command(tm, MPR_RECOVERY, 1505265236Sken "finished recovery after aborting TaskMID %u\n", 1506265236Sken le16toh(req->TaskMID)); 1507265236Sken 1508265236Sken targ->tm = NULL; 1509265236Sken mprsas_free_tm(sc, tm); 1510265236Sken } 1511265236Sken else if (le16toh(req->TaskMID) != cm->cm_desc.Default.SMID) { 1512265236Sken /* abort success, but we have more timedout commands to abort */ 1513265236Sken mprsas_log_command(tm, MPR_RECOVERY, 1514265236Sken "continuing recovery after aborting TaskMID %u\n", 1515265236Sken le16toh(req->TaskMID)); 1516265236Sken 1517265236Sken mprsas_send_abort(sc, tm, cm); 1518265236Sken } 1519265236Sken else { 1520265236Sken /* we didn't get a command completion, so the abort 1521265236Sken * failed as far as we're concerned. escalate. 1522265236Sken */ 1523265236Sken mprsas_log_command(tm, MPR_RECOVERY, 1524265236Sken "abort failed for TaskMID %u tm %p\n", 1525265236Sken le16toh(req->TaskMID), tm); 1526265236Sken 1527265236Sken mprsas_send_reset(sc, tm, 1528265236Sken MPI2_SCSITASKMGMT_TASKTYPE_LOGICAL_UNIT_RESET); 1529265236Sken } 1530265236Sken} 1531265236Sken 1532265236Sken#define MPR_ABORT_TIMEOUT 5 1533265236Sken 1534265236Skenstatic int 1535265236Skenmprsas_send_abort(struct mpr_softc *sc, struct mpr_command *tm, 1536265236Sken struct mpr_command *cm) 1537265236Sken{ 1538265236Sken MPI2_SCSI_TASK_MANAGE_REQUEST *req; 1539265236Sken struct mprsas_target *targ; 1540265236Sken int err; 1541265236Sken 1542265236Sken targ = cm->cm_targ; 1543265236Sken if (targ->handle == 0) { 1544265236Sken mpr_dprint(sc, MPR_ERROR,"%s null devhandle for target_id %d\n", 1545265236Sken __func__, cm->cm_ccb->ccb_h.target_id); 1546265236Sken return -1; 1547265236Sken } 1548265236Sken 1549265236Sken mprsas_log_command(tm, MPR_RECOVERY|MPR_INFO, 1550265236Sken "Aborting command %p\n", cm); 1551265236Sken 1552265236Sken req = (MPI2_SCSI_TASK_MANAGE_REQUEST *)tm->cm_req; 1553265236Sken req->DevHandle = htole16(targ->handle); 1554265236Sken req->Function = MPI2_FUNCTION_SCSI_TASK_MGMT; 1555265236Sken req->TaskType = MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK; 1556265236Sken 1557265236Sken /* XXX Need to handle invalid LUNs */ 1558265236Sken MPR_SET_LUN(req->LUN, cm->cm_ccb->ccb_h.target_lun); 1559265236Sken 1560265236Sken req->TaskMID = htole16(cm->cm_desc.Default.SMID); 1561265236Sken 1562265236Sken tm->cm_data = NULL; 1563265236Sken tm->cm_desc.HighPriority.RequestFlags = 1564265236Sken MPI2_REQ_DESCRIPT_FLAGS_HIGH_PRIORITY; 1565265236Sken tm->cm_complete = mprsas_abort_complete; 1566265236Sken tm->cm_complete_data = (void *)tm; 1567265236Sken tm->cm_targ = cm->cm_targ; 1568265236Sken tm->cm_lun = cm->cm_lun; 1569265236Sken 1570265236Sken callout_reset(&tm->cm_callout, MPR_ABORT_TIMEOUT * hz, 1571265236Sken mprsas_tm_timeout, tm); 1572265236Sken 1573265236Sken targ->aborts++; 1574265236Sken 1575265236Sken err = mpr_map_command(sc, tm); 1576265236Sken if (err) 1577265236Sken mprsas_log_command(tm, MPR_RECOVERY, 1578265236Sken "error %d sending abort for cm %p SMID %u\n", 1579265236Sken err, cm, req->TaskMID); 1580265236Sken return err; 1581265236Sken} 1582265236Sken 1583265236Sken 1584265236Skenstatic void 1585265236Skenmprsas_scsiio_timeout(void *data) 1586265236Sken{ 1587265236Sken struct mpr_softc *sc; 1588265236Sken struct mpr_command *cm; 1589265236Sken struct mprsas_target *targ; 1590265236Sken 1591265236Sken cm = (struct mpr_command *)data; 1592265236Sken sc = cm->cm_sc; 1593265236Sken 1594265236Sken MPR_FUNCTRACE(sc); 1595265236Sken mtx_assert(&sc->mpr_mtx, MA_OWNED); 1596265236Sken 1597265236Sken mpr_dprint(sc, MPR_XINFO, "Timeout checking cm %p\n", cm); 1598265236Sken 1599265236Sken /* 1600265236Sken * Run the interrupt handler to make sure it's not pending. This 1601265236Sken * isn't perfect because the command could have already completed 1602265236Sken * and been re-used, though this is unlikely. 1603265236Sken */ 1604265236Sken mpr_intr_locked(sc); 1605265236Sken if (cm->cm_state == MPR_CM_STATE_FREE) { 1606265236Sken mprsas_log_command(cm, MPR_XINFO, 1607265236Sken "SCSI command %p almost timed out\n", cm); 1608265236Sken return; 1609265236Sken } 1610265236Sken 1611265236Sken if (cm->cm_ccb == NULL) { 1612265236Sken mpr_dprint(sc, MPR_ERROR, "command timeout with NULL ccb\n"); 1613265236Sken return; 1614265236Sken } 1615265236Sken 1616265236Sken targ = cm->cm_targ; 1617265236Sken targ->timeouts++; 1618265236Sken 1619265236Sken mprsas_log_command(cm, MPR_XINFO, "command timeout cm %p ccb %p " 1620265236Sken "target %u, handle(0x%04x)\n", cm, cm->cm_ccb, targ->tid, 1621265236Sken targ->handle); 1622265236Sken if (targ->encl_level_valid) { 1623265236Sken mpr_dprint(sc, MPR_XINFO, "At enclosure level %d, slot %d, " 1624265236Sken "connector name (%4s)\n", targ->encl_level, targ->encl_slot, 1625265236Sken targ->connector_name); 1626265236Sken } 1627265236Sken 1628265236Sken /* XXX first, check the firmware state, to see if it's still 1629265236Sken * operational. if not, do a diag reset. 1630265236Sken */ 1631265236Sken 1632265236Sken cm->cm_ccb->ccb_h.status = CAM_CMD_TIMEOUT; 1633265236Sken cm->cm_state = MPR_CM_STATE_TIMEDOUT; 1634265236Sken TAILQ_INSERT_TAIL(&targ->timedout_commands, cm, cm_recovery); 1635265236Sken 1636265236Sken if (targ->tm != NULL) { 1637265236Sken /* target already in recovery, just queue up another 1638265236Sken * timedout command to be processed later. 1639265236Sken */ 1640265236Sken mpr_dprint(sc, MPR_RECOVERY, "queued timedout cm %p for " 1641265236Sken "processing by tm %p\n", cm, targ->tm); 1642265236Sken } 1643265236Sken else if ((targ->tm = mprsas_alloc_tm(sc)) != NULL) { 1644265236Sken mpr_dprint(sc, MPR_RECOVERY, "timedout cm %p allocated tm %p\n", 1645265236Sken cm, targ->tm); 1646265236Sken 1647265236Sken /* start recovery by aborting the first timedout command */ 1648265236Sken mprsas_send_abort(sc, targ->tm, cm); 1649265236Sken } 1650265236Sken else { 1651265236Sken /* XXX queue this target up for recovery once a TM becomes 1652265236Sken * available. The firmware only has a limited number of 1653265236Sken * HighPriority credits for the high priority requests used 1654265236Sken * for task management, and we ran out. 1655265236Sken * 1656265236Sken * Isilon: don't worry about this for now, since we have 1657265236Sken * more credits than disks in an enclosure, and limit 1658265236Sken * ourselves to one TM per target for recovery. 1659265236Sken */ 1660265236Sken mpr_dprint(sc, MPR_RECOVERY, 1661265236Sken "timedout cm %p failed to allocate a tm\n", cm); 1662265236Sken } 1663265236Sken} 1664265236Sken 1665265236Skenstatic void 1666265236Skenmprsas_action_scsiio(struct mprsas_softc *sassc, union ccb *ccb) 1667265236Sken{ 1668265236Sken MPI2_SCSI_IO_REQUEST *req; 1669265236Sken struct ccb_scsiio *csio; 1670265236Sken struct mpr_softc *sc; 1671265236Sken struct mprsas_target *targ; 1672265236Sken struct mprsas_lun *lun; 1673265236Sken struct mpr_command *cm; 1674265236Sken uint8_t i, lba_byte, *ref_tag_addr; 1675265236Sken uint16_t eedp_flags; 1676265236Sken uint32_t mpi_control; 1677265236Sken 1678265236Sken sc = sassc->sc; 1679265236Sken MPR_FUNCTRACE(sc); 1680265236Sken mtx_assert(&sc->mpr_mtx, MA_OWNED); 1681265236Sken 1682265236Sken csio = &ccb->csio; 1683265236Sken targ = &sassc->targets[csio->ccb_h.target_id]; 1684265236Sken mpr_dprint(sc, MPR_TRACE, "ccb %p target flag %x\n", ccb, targ->flags); 1685265236Sken if (targ->handle == 0x0) { 1686265236Sken mpr_dprint(sc, MPR_ERROR, "%s NULL handle for target %u\n", 1687265236Sken __func__, csio->ccb_h.target_id); 1688265236Sken csio->ccb_h.status = CAM_DEV_NOT_THERE; 1689265236Sken xpt_done(ccb); 1690265236Sken return; 1691265236Sken } 1692265236Sken if (targ->flags & MPR_TARGET_FLAGS_RAID_COMPONENT) { 1693265236Sken mpr_dprint(sc, MPR_TRACE, "%s Raid component no SCSI IO " 1694265236Sken "supported %u\n", __func__, csio->ccb_h.target_id); 1695265236Sken csio->ccb_h.status = CAM_DEV_NOT_THERE; 1696265236Sken xpt_done(ccb); 1697265236Sken return; 1698265236Sken } 1699265236Sken /* 1700265236Sken * Sometimes, it is possible to get a command that is not "In 1701265236Sken * Progress" and was actually aborted by the upper layer. Check for 1702265236Sken * this here and complete the command without error. 1703265236Sken */ 1704265236Sken if (ccb->ccb_h.status != CAM_REQ_INPROG) { 1705265236Sken mpr_dprint(sc, MPR_TRACE, "%s Command is not in progress for " 1706265236Sken "target %u\n", __func__, csio->ccb_h.target_id); 1707265236Sken xpt_done(ccb); 1708265236Sken return; 1709265236Sken } 1710265236Sken /* 1711265236Sken * If devinfo is 0 this will be a volume. In that case don't tell CAM 1712265236Sken * that the volume has timed out. We want volumes to be enumerated 1713265236Sken * until they are deleted/removed, not just failed. 1714265236Sken */ 1715265236Sken if (targ->flags & MPRSAS_TARGET_INREMOVAL) { 1716265236Sken if (targ->devinfo == 0) 1717265236Sken csio->ccb_h.status = CAM_REQ_CMP; 1718265236Sken else 1719265236Sken csio->ccb_h.status = CAM_SEL_TIMEOUT; 1720265236Sken xpt_done(ccb); 1721265236Sken return; 1722265236Sken } 1723265236Sken 1724265236Sken if ((sc->mpr_flags & MPR_FLAGS_SHUTDOWN) != 0) { 1725265236Sken mpr_dprint(sc, MPR_TRACE, "%s shutting down\n", __func__); 1726265236Sken csio->ccb_h.status = CAM_DEV_NOT_THERE; 1727265236Sken xpt_done(ccb); 1728265236Sken return; 1729265236Sken } 1730265236Sken 1731265236Sken cm = mpr_alloc_command(sc); 1732265236Sken if (cm == NULL || (sc->mpr_flags & MPR_FLAGS_DIAGRESET)) { 1733265236Sken if (cm != NULL) { 1734265236Sken mpr_free_command(sc, cm); 1735265236Sken } 1736265236Sken if ((sassc->flags & MPRSAS_QUEUE_FROZEN) == 0) { 1737265236Sken xpt_freeze_simq(sassc->sim, 1); 1738265236Sken sassc->flags |= MPRSAS_QUEUE_FROZEN; 1739265236Sken } 1740265236Sken ccb->ccb_h.status &= ~CAM_SIM_QUEUED; 1741265236Sken ccb->ccb_h.status |= CAM_REQUEUE_REQ; 1742265236Sken xpt_done(ccb); 1743265236Sken return; 1744265236Sken } 1745265236Sken 1746265236Sken req = (MPI2_SCSI_IO_REQUEST *)cm->cm_req; 1747265236Sken bzero(req, sizeof(*req)); 1748265236Sken req->DevHandle = htole16(targ->handle); 1749265236Sken req->Function = MPI2_FUNCTION_SCSI_IO_REQUEST; 1750265236Sken req->MsgFlags = 0; 1751265236Sken req->SenseBufferLowAddress = htole32(cm->cm_sense_busaddr); 1752265236Sken req->SenseBufferLength = MPR_SENSE_LEN; 1753265236Sken req->SGLFlags = 0; 1754265236Sken req->ChainOffset = 0; 1755265236Sken req->SGLOffset0 = 24; /* 32bit word offset to the SGL */ 1756265236Sken req->SGLOffset1= 0; 1757265236Sken req->SGLOffset2= 0; 1758265236Sken req->SGLOffset3= 0; 1759265236Sken req->SkipCount = 0; 1760265236Sken req->DataLength = htole32(csio->dxfer_len); 1761265236Sken req->BidirectionalDataLength = 0; 1762265236Sken req->IoFlags = htole16(csio->cdb_len); 1763265236Sken req->EEDPFlags = 0; 1764265236Sken 1765265236Sken /* Note: BiDirectional transfers are not supported */ 1766265236Sken switch (csio->ccb_h.flags & CAM_DIR_MASK) { 1767265236Sken case CAM_DIR_IN: 1768265236Sken mpi_control = MPI2_SCSIIO_CONTROL_READ; 1769265236Sken cm->cm_flags |= MPR_CM_FLAGS_DATAIN; 1770265236Sken break; 1771265236Sken case CAM_DIR_OUT: 1772265236Sken mpi_control = MPI2_SCSIIO_CONTROL_WRITE; 1773265236Sken cm->cm_flags |= MPR_CM_FLAGS_DATAOUT; 1774265236Sken break; 1775265236Sken case CAM_DIR_NONE: 1776265236Sken default: 1777265236Sken mpi_control = MPI2_SCSIIO_CONTROL_NODATATRANSFER; 1778265236Sken break; 1779265236Sken } 1780265236Sken 1781265236Sken if (csio->cdb_len == 32) 1782265236Sken mpi_control |= 4 << MPI2_SCSIIO_CONTROL_ADDCDBLEN_SHIFT; 1783265236Sken /* 1784265236Sken * It looks like the hardware doesn't require an explicit tag 1785265236Sken * number for each transaction. SAM Task Management not supported 1786265236Sken * at the moment. 1787265236Sken */ 1788265236Sken switch (csio->tag_action) { 1789265236Sken case MSG_HEAD_OF_Q_TAG: 1790265236Sken mpi_control |= MPI2_SCSIIO_CONTROL_HEADOFQ; 1791265236Sken break; 1792265236Sken case MSG_ORDERED_Q_TAG: 1793265236Sken mpi_control |= MPI2_SCSIIO_CONTROL_ORDEREDQ; 1794265236Sken break; 1795265236Sken case MSG_ACA_TASK: 1796265236Sken mpi_control |= MPI2_SCSIIO_CONTROL_ACAQ; 1797265236Sken break; 1798265236Sken case CAM_TAG_ACTION_NONE: 1799265236Sken case MSG_SIMPLE_Q_TAG: 1800265236Sken default: 1801265236Sken mpi_control |= MPI2_SCSIIO_CONTROL_SIMPLEQ; 1802265236Sken break; 1803265236Sken } 1804265236Sken mpi_control |= sc->mapping_table[csio->ccb_h.target_id].TLR_bits; 1805265236Sken req->Control = htole32(mpi_control); 1806265236Sken 1807265236Sken if (MPR_SET_LUN(req->LUN, csio->ccb_h.target_lun) != 0) { 1808265236Sken mpr_free_command(sc, cm); 1809265236Sken ccb->ccb_h.status = CAM_LUN_INVALID; 1810265236Sken xpt_done(ccb); 1811265236Sken return; 1812265236Sken } 1813265236Sken 1814265236Sken if (csio->ccb_h.flags & CAM_CDB_POINTER) 1815265236Sken bcopy(csio->cdb_io.cdb_ptr, &req->CDB.CDB32[0], csio->cdb_len); 1816265236Sken else 1817265236Sken bcopy(csio->cdb_io.cdb_bytes, &req->CDB.CDB32[0],csio->cdb_len); 1818265236Sken req->IoFlags = htole16(csio->cdb_len); 1819265236Sken 1820265236Sken /* 1821265236Sken * Check if EEDP is supported and enabled. If it is then check if the 1822265236Sken * SCSI opcode could be using EEDP. If so, make sure the LUN exists and 1823265236Sken * is formatted for EEDP support. If all of this is true, set CDB up 1824265236Sken * for EEDP transfer. 1825265236Sken */ 1826265236Sken eedp_flags = op_code_prot[req->CDB.CDB32[0]]; 1827265236Sken if (sc->eedp_enabled && eedp_flags) { 1828265236Sken SLIST_FOREACH(lun, &targ->luns, lun_link) { 1829265236Sken if (lun->lun_id == csio->ccb_h.target_lun) { 1830265236Sken break; 1831265236Sken } 1832265236Sken } 1833265236Sken 1834265236Sken if ((lun != NULL) && (lun->eedp_formatted)) { 1835265236Sken req->EEDPBlockSize = htole16(lun->eedp_block_size); 1836265236Sken eedp_flags |= (MPI2_SCSIIO_EEDPFLAGS_INC_PRI_REFTAG | 1837265236Sken MPI2_SCSIIO_EEDPFLAGS_CHECK_REFTAG | 1838265236Sken MPI2_SCSIIO_EEDPFLAGS_CHECK_GUARD); 1839265236Sken req->EEDPFlags = htole16(eedp_flags); 1840265236Sken 1841265236Sken /* 1842265236Sken * If CDB less than 32, fill in Primary Ref Tag with 1843265236Sken * low 4 bytes of LBA. If CDB is 32, tag stuff is 1844265236Sken * already there. Also, set protection bit. FreeBSD 1845265236Sken * currently does not support CDBs bigger than 16, but 1846265236Sken * the code doesn't hurt, and will be here for the 1847265236Sken * future. 1848265236Sken */ 1849265236Sken if (csio->cdb_len != 32) { 1850265236Sken lba_byte = (csio->cdb_len == 16) ? 6 : 2; 1851265236Sken ref_tag_addr = (uint8_t *)&req->CDB.EEDP32. 1852265236Sken PrimaryReferenceTag; 1853265236Sken for (i = 0; i < 4; i++) { 1854265236Sken *ref_tag_addr = 1855265236Sken req->CDB.CDB32[lba_byte + i]; 1856265236Sken ref_tag_addr++; 1857265236Sken } 1858265236Sken req->CDB.EEDP32.PrimaryReferenceTag = 1859265236Sken htole32(req-> 1860265236Sken CDB.EEDP32.PrimaryReferenceTag); 1861265236Sken req->CDB.EEDP32.PrimaryApplicationTagMask = 1862265236Sken 0xFFFF; 1863265236Sken req->CDB.CDB32[1] = (req->CDB.CDB32[1] & 0x1F) | 1864265236Sken 0x20; 1865265236Sken } else { 1866265236Sken eedp_flags |= 1867265236Sken MPI2_SCSIIO_EEDPFLAGS_INC_PRI_APPTAG; 1868265236Sken req->EEDPFlags = htole16(eedp_flags); 1869265236Sken req->CDB.CDB32[10] = (req->CDB.CDB32[10] & 1870265236Sken 0x1F) | 0x20; 1871265236Sken } 1872265236Sken } 1873265236Sken } 1874265236Sken 1875265236Sken cm->cm_length = csio->dxfer_len; 1876265236Sken if (cm->cm_length != 0) { 1877265236Sken cm->cm_data = ccb; 1878265236Sken cm->cm_flags |= MPR_CM_FLAGS_USE_CCB; 1879265236Sken } else { 1880265236Sken cm->cm_data = NULL; 1881265236Sken } 1882265236Sken cm->cm_sge = &req->SGL; 1883265236Sken cm->cm_sglsize = (32 - 24) * 4; 1884265236Sken cm->cm_complete = mprsas_scsiio_complete; 1885265236Sken cm->cm_complete_data = ccb; 1886265236Sken cm->cm_targ = targ; 1887265236Sken cm->cm_lun = csio->ccb_h.target_lun; 1888265236Sken cm->cm_ccb = ccb; 1889265236Sken /* 1890265236Sken * If using FP desc type, need to set a bit in IoFlags (SCSI IO is 0) 1891265236Sken * and set descriptor type. 1892265236Sken */ 1893265236Sken if (targ->scsi_req_desc_type == 1894265236Sken MPI25_REQ_DESCRIPT_FLAGS_FAST_PATH_SCSI_IO) { 1895265236Sken req->IoFlags |= MPI25_SCSIIO_IOFLAGS_FAST_PATH; 1896265236Sken cm->cm_desc.FastPathSCSIIO.RequestFlags = 1897265236Sken MPI25_REQ_DESCRIPT_FLAGS_FAST_PATH_SCSI_IO; 1898265236Sken cm->cm_desc.FastPathSCSIIO.DevHandle = htole16(targ->handle); 1899265236Sken } else { 1900265236Sken cm->cm_desc.SCSIIO.RequestFlags = 1901265236Sken MPI2_REQ_DESCRIPT_FLAGS_SCSI_IO; 1902265236Sken cm->cm_desc.SCSIIO.DevHandle = htole16(targ->handle); 1903265236Sken } 1904265236Sken 1905265236Sken callout_reset(&cm->cm_callout, (ccb->ccb_h.timeout * hz) / 1000, 1906265236Sken mprsas_scsiio_timeout, cm); 1907265236Sken 1908265236Sken targ->issued++; 1909265236Sken targ->outstanding++; 1910265236Sken TAILQ_INSERT_TAIL(&targ->commands, cm, cm_link); 1911265236Sken ccb->ccb_h.status |= CAM_SIM_QUEUED; 1912265236Sken 1913265236Sken mprsas_log_command(cm, MPR_XINFO, "%s cm %p ccb %p outstanding %u\n", 1914265236Sken __func__, cm, ccb, targ->outstanding); 1915265236Sken 1916265236Sken mpr_map_command(sc, cm); 1917265236Sken return; 1918265236Sken} 1919265236Sken 1920265236Skenstatic void 1921265236Skenmpr_response_code(struct mpr_softc *sc, u8 response_code) 1922265236Sken{ 1923265236Sken char *desc; 1924265236Sken 1925265236Sken switch (response_code) { 1926265236Sken case MPI2_SCSITASKMGMT_RSP_TM_COMPLETE: 1927265236Sken desc = "task management request completed"; 1928265236Sken break; 1929265236Sken case MPI2_SCSITASKMGMT_RSP_INVALID_FRAME: 1930265236Sken desc = "invalid frame"; 1931265236Sken break; 1932265236Sken case MPI2_SCSITASKMGMT_RSP_TM_NOT_SUPPORTED: 1933265236Sken desc = "task management request not supported"; 1934265236Sken break; 1935265236Sken case MPI2_SCSITASKMGMT_RSP_TM_FAILED: 1936265236Sken desc = "task management request failed"; 1937265236Sken break; 1938265236Sken case MPI2_SCSITASKMGMT_RSP_TM_SUCCEEDED: 1939265236Sken desc = "task management request succeeded"; 1940265236Sken break; 1941265236Sken case MPI2_SCSITASKMGMT_RSP_TM_INVALID_LUN: 1942265236Sken desc = "invalid lun"; 1943265236Sken break; 1944265236Sken case 0xA: 1945265236Sken desc = "overlapped tag attempted"; 1946265236Sken break; 1947265236Sken case MPI2_SCSITASKMGMT_RSP_IO_QUEUED_ON_IOC: 1948265236Sken desc = "task queued, however not sent to target"; 1949265236Sken break; 1950265236Sken default: 1951265236Sken desc = "unknown"; 1952265236Sken break; 1953265236Sken } 1954265236Sken mpr_dprint(sc, MPR_XINFO, "response_code(0x%01x): %s\n", response_code, 1955265236Sken desc); 1956265236Sken} 1957265236Sken 1958265236Sken/** 1959265236Sken * mpr_sc_failed_io_info - translated non-succesfull SCSI_IO request 1960265236Sken */ 1961265236Skenstatic void 1962265236Skenmpr_sc_failed_io_info(struct mpr_softc *sc, struct ccb_scsiio *csio, 1963265236Sken Mpi2SCSIIOReply_t *mpi_reply, struct mprsas_target *targ) 1964265236Sken{ 1965265236Sken u32 response_info; 1966265236Sken u8 *response_bytes; 1967265236Sken u16 ioc_status = le16toh(mpi_reply->IOCStatus) & 1968265236Sken MPI2_IOCSTATUS_MASK; 1969265236Sken u8 scsi_state = mpi_reply->SCSIState; 1970265236Sken u8 scsi_status = mpi_reply->SCSIStatus; 1971265236Sken char *desc_ioc_state = NULL; 1972265236Sken char *desc_scsi_status = NULL; 1973265236Sken char *desc_scsi_state = sc->tmp_string; 1974265236Sken u32 log_info = le32toh(mpi_reply->IOCLogInfo); 1975265236Sken 1976265236Sken if (log_info == 0x31170000) 1977265236Sken return; 1978265236Sken 1979265236Sken switch (ioc_status) { 1980265236Sken case MPI2_IOCSTATUS_SUCCESS: 1981265236Sken desc_ioc_state = "success"; 1982265236Sken break; 1983265236Sken case MPI2_IOCSTATUS_INVALID_FUNCTION: 1984265236Sken desc_ioc_state = "invalid function"; 1985265236Sken break; 1986265236Sken case MPI2_IOCSTATUS_SCSI_RECOVERED_ERROR: 1987265236Sken desc_ioc_state = "scsi recovered error"; 1988265236Sken break; 1989265236Sken case MPI2_IOCSTATUS_SCSI_INVALID_DEVHANDLE: 1990265236Sken desc_ioc_state = "scsi invalid dev handle"; 1991265236Sken break; 1992265236Sken case MPI2_IOCSTATUS_SCSI_DEVICE_NOT_THERE: 1993265236Sken desc_ioc_state = "scsi device not there"; 1994265236Sken break; 1995265236Sken case MPI2_IOCSTATUS_SCSI_DATA_OVERRUN: 1996265236Sken desc_ioc_state = "scsi data overrun"; 1997265236Sken break; 1998265236Sken case MPI2_IOCSTATUS_SCSI_DATA_UNDERRUN: 1999265236Sken desc_ioc_state = "scsi data underrun"; 2000265236Sken break; 2001265236Sken case MPI2_IOCSTATUS_SCSI_IO_DATA_ERROR: 2002265236Sken desc_ioc_state = "scsi io data error"; 2003265236Sken break; 2004265236Sken case MPI2_IOCSTATUS_SCSI_PROTOCOL_ERROR: 2005265236Sken desc_ioc_state = "scsi protocol error"; 2006265236Sken break; 2007265236Sken case MPI2_IOCSTATUS_SCSI_TASK_TERMINATED: 2008265236Sken desc_ioc_state = "scsi task terminated"; 2009265236Sken break; 2010265236Sken case MPI2_IOCSTATUS_SCSI_RESIDUAL_MISMATCH: 2011265236Sken desc_ioc_state = "scsi residual mismatch"; 2012265236Sken break; 2013265236Sken case MPI2_IOCSTATUS_SCSI_TASK_MGMT_FAILED: 2014265236Sken desc_ioc_state = "scsi task mgmt failed"; 2015265236Sken break; 2016265236Sken case MPI2_IOCSTATUS_SCSI_IOC_TERMINATED: 2017265236Sken desc_ioc_state = "scsi ioc terminated"; 2018265236Sken break; 2019265236Sken case MPI2_IOCSTATUS_SCSI_EXT_TERMINATED: 2020265236Sken desc_ioc_state = "scsi ext terminated"; 2021265236Sken break; 2022265236Sken case MPI2_IOCSTATUS_EEDP_GUARD_ERROR: 2023265236Sken desc_ioc_state = "eedp guard error"; 2024265236Sken break; 2025265236Sken case MPI2_IOCSTATUS_EEDP_REF_TAG_ERROR: 2026265236Sken desc_ioc_state = "eedp ref tag error"; 2027265236Sken break; 2028265236Sken case MPI2_IOCSTATUS_EEDP_APP_TAG_ERROR: 2029265236Sken desc_ioc_state = "eedp app tag error"; 2030265236Sken break; 2031265236Sken default: 2032265236Sken desc_ioc_state = "unknown"; 2033265236Sken break; 2034265236Sken } 2035265236Sken 2036265236Sken switch (scsi_status) { 2037265236Sken case MPI2_SCSI_STATUS_GOOD: 2038265236Sken desc_scsi_status = "good"; 2039265236Sken break; 2040265236Sken case MPI2_SCSI_STATUS_CHECK_CONDITION: 2041265236Sken desc_scsi_status = "check condition"; 2042265236Sken break; 2043265236Sken case MPI2_SCSI_STATUS_CONDITION_MET: 2044265236Sken desc_scsi_status = "condition met"; 2045265236Sken break; 2046265236Sken case MPI2_SCSI_STATUS_BUSY: 2047265236Sken desc_scsi_status = "busy"; 2048265236Sken break; 2049265236Sken case MPI2_SCSI_STATUS_INTERMEDIATE: 2050265236Sken desc_scsi_status = "intermediate"; 2051265236Sken break; 2052265236Sken case MPI2_SCSI_STATUS_INTERMEDIATE_CONDMET: 2053265236Sken desc_scsi_status = "intermediate condmet"; 2054265236Sken break; 2055265236Sken case MPI2_SCSI_STATUS_RESERVATION_CONFLICT: 2056265236Sken desc_scsi_status = "reservation conflict"; 2057265236Sken break; 2058265236Sken case MPI2_SCSI_STATUS_COMMAND_TERMINATED: 2059265236Sken desc_scsi_status = "command terminated"; 2060265236Sken break; 2061265236Sken case MPI2_SCSI_STATUS_TASK_SET_FULL: 2062265236Sken desc_scsi_status = "task set full"; 2063265236Sken break; 2064265236Sken case MPI2_SCSI_STATUS_ACA_ACTIVE: 2065265236Sken desc_scsi_status = "aca active"; 2066265236Sken break; 2067265236Sken case MPI2_SCSI_STATUS_TASK_ABORTED: 2068265236Sken desc_scsi_status = "task aborted"; 2069265236Sken break; 2070265236Sken default: 2071265236Sken desc_scsi_status = "unknown"; 2072265236Sken break; 2073265236Sken } 2074265236Sken 2075265236Sken desc_scsi_state[0] = '\0'; 2076265236Sken if (!scsi_state) 2077265236Sken desc_scsi_state = " "; 2078265236Sken if (scsi_state & MPI2_SCSI_STATE_RESPONSE_INFO_VALID) 2079265236Sken strcat(desc_scsi_state, "response info "); 2080265236Sken if (scsi_state & MPI2_SCSI_STATE_TERMINATED) 2081265236Sken strcat(desc_scsi_state, "state terminated "); 2082265236Sken if (scsi_state & MPI2_SCSI_STATE_NO_SCSI_STATUS) 2083265236Sken strcat(desc_scsi_state, "no status "); 2084265236Sken if (scsi_state & MPI2_SCSI_STATE_AUTOSENSE_FAILED) 2085265236Sken strcat(desc_scsi_state, "autosense failed "); 2086265236Sken if (scsi_state & MPI2_SCSI_STATE_AUTOSENSE_VALID) 2087265236Sken strcat(desc_scsi_state, "autosense valid "); 2088265236Sken 2089265236Sken mpr_dprint(sc, MPR_XINFO, "\thandle(0x%04x), ioc_status(%s)(0x%04x)\n", 2090265236Sken le16toh(mpi_reply->DevHandle), desc_ioc_state, ioc_status); 2091265236Sken if (targ->encl_level_valid) { 2092265236Sken mpr_dprint(sc, MPR_XINFO, "At enclosure level %d, slot %d, " 2093265236Sken "connector name (%4s)\n", targ->encl_level, targ->encl_slot, 2094265236Sken targ->connector_name); 2095265236Sken } 2096265236Sken /* We can add more detail about underflow data here 2097265236Sken * TO-DO 2098265236Sken * */ 2099265236Sken mpr_dprint(sc, MPR_XINFO, "\tscsi_status(%s)(0x%02x), " 2100265236Sken "scsi_state(%s)(0x%02x)\n", desc_scsi_status, scsi_status, 2101265236Sken desc_scsi_state, scsi_state); 2102265236Sken 2103265236Sken if (sc->mpr_debug & MPR_XINFO && 2104265236Sken scsi_state & MPI2_SCSI_STATE_AUTOSENSE_VALID) { 2105265236Sken mpr_dprint(sc, MPR_XINFO, "-> Sense Buffer Data : Start :\n"); 2106265236Sken scsi_sense_print(csio); 2107265236Sken mpr_dprint(sc, MPR_XINFO, "-> Sense Buffer Data : End :\n"); 2108265236Sken } 2109265236Sken 2110265236Sken if (scsi_state & MPI2_SCSI_STATE_RESPONSE_INFO_VALID) { 2111265236Sken response_info = le32toh(mpi_reply->ResponseInfo); 2112265236Sken response_bytes = (u8 *)&response_info; 2113265236Sken mpr_response_code(sc,response_bytes[0]); 2114265236Sken } 2115265236Sken} 2116265236Sken 2117265236Skenstatic void 2118265236Skenmprsas_scsiio_complete(struct mpr_softc *sc, struct mpr_command *cm) 2119265236Sken{ 2120265236Sken MPI2_SCSI_IO_REPLY *rep; 2121265236Sken union ccb *ccb; 2122265236Sken struct ccb_scsiio *csio; 2123265236Sken struct mprsas_softc *sassc; 2124265236Sken struct scsi_vpd_supported_page_list *vpd_list = NULL; 2125265236Sken u8 *TLR_bits, TLR_on; 2126265236Sken int dir = 0, i; 2127265236Sken u16 alloc_len; 2128265236Sken 2129265236Sken MPR_FUNCTRACE(sc); 2130265236Sken mpr_dprint(sc, MPR_TRACE, 2131265236Sken "cm %p SMID %u ccb %p reply %p outstanding %u\n", cm, 2132265236Sken cm->cm_desc.Default.SMID, cm->cm_ccb, cm->cm_reply, 2133265236Sken cm->cm_targ->outstanding); 2134265236Sken 2135265236Sken callout_stop(&cm->cm_callout); 2136265236Sken mtx_assert(&sc->mpr_mtx, MA_OWNED); 2137265236Sken 2138265236Sken sassc = sc->sassc; 2139265236Sken ccb = cm->cm_complete_data; 2140265236Sken csio = &ccb->csio; 2141265236Sken rep = (MPI2_SCSI_IO_REPLY *)cm->cm_reply; 2142265236Sken /* 2143265236Sken * XXX KDM if the chain allocation fails, does it matter if we do 2144265236Sken * the sync and unload here? It is simpler to do it in every case, 2145265236Sken * assuming it doesn't cause problems. 2146265236Sken */ 2147265236Sken if (cm->cm_data != NULL) { 2148265236Sken if (cm->cm_flags & MPR_CM_FLAGS_DATAIN) 2149265236Sken dir = BUS_DMASYNC_POSTREAD; 2150265236Sken else if (cm->cm_flags & MPR_CM_FLAGS_DATAOUT) 2151265236Sken dir = BUS_DMASYNC_POSTWRITE; 2152265236Sken bus_dmamap_sync(sc->buffer_dmat, cm->cm_dmamap, dir); 2153265236Sken bus_dmamap_unload(sc->buffer_dmat, cm->cm_dmamap); 2154265236Sken } 2155265236Sken 2156265236Sken cm->cm_targ->completed++; 2157265236Sken cm->cm_targ->outstanding--; 2158265236Sken TAILQ_REMOVE(&cm->cm_targ->commands, cm, cm_link); 2159265236Sken ccb->ccb_h.status &= ~(CAM_STATUS_MASK | CAM_SIM_QUEUED); 2160265236Sken 2161265236Sken if (cm->cm_state == MPR_CM_STATE_TIMEDOUT) { 2162265236Sken TAILQ_REMOVE(&cm->cm_targ->timedout_commands, cm, cm_recovery); 2163265236Sken if (cm->cm_reply != NULL) 2164265236Sken mprsas_log_command(cm, MPR_RECOVERY, 2165265236Sken "completed timedout cm %p ccb %p during recovery " 2166265236Sken "ioc %x scsi %x state %x xfer %u\n", cm, cm->cm_ccb, 2167265236Sken le16toh(rep->IOCStatus), rep->SCSIStatus, 2168265236Sken rep->SCSIState, le32toh(rep->TransferCount)); 2169265236Sken else 2170265236Sken mprsas_log_command(cm, MPR_RECOVERY, 2171265236Sken "completed timedout cm %p ccb %p during recovery\n", 2172265236Sken cm, cm->cm_ccb); 2173265236Sken } else if (cm->cm_targ->tm != NULL) { 2174265236Sken if (cm->cm_reply != NULL) 2175265236Sken mprsas_log_command(cm, MPR_RECOVERY, 2176265236Sken "completed cm %p ccb %p during recovery " 2177265236Sken "ioc %x scsi %x state %x xfer %u\n", 2178265236Sken cm, cm->cm_ccb, le16toh(rep->IOCStatus), 2179265236Sken rep->SCSIStatus, rep->SCSIState, 2180265236Sken le32toh(rep->TransferCount)); 2181265236Sken else 2182265236Sken mprsas_log_command(cm, MPR_RECOVERY, 2183265236Sken "completed cm %p ccb %p during recovery\n", 2184265236Sken cm, cm->cm_ccb); 2185265236Sken } else if ((sc->mpr_flags & MPR_FLAGS_DIAGRESET) != 0) { 2186265236Sken mprsas_log_command(cm, MPR_RECOVERY, 2187265236Sken "reset completed cm %p ccb %p\n", cm, cm->cm_ccb); 2188265236Sken } 2189265236Sken 2190265236Sken if ((cm->cm_flags & MPR_CM_FLAGS_ERROR_MASK) != 0) { 2191265236Sken /* 2192265236Sken * We ran into an error after we tried to map the command, 2193265236Sken * so we're getting a callback without queueing the command 2194265236Sken * to the hardware. So we set the status here, and it will 2195265236Sken * be retained below. We'll go through the "fast path", 2196265236Sken * because there can be no reply when we haven't actually 2197265236Sken * gone out to the hardware. 2198265236Sken */ 2199265236Sken ccb->ccb_h.status = CAM_REQUEUE_REQ; 2200265236Sken 2201265236Sken /* 2202265236Sken * Currently the only error included in the mask is 2203265236Sken * MPR_CM_FLAGS_CHAIN_FAILED, which means we're out of 2204265236Sken * chain frames. We need to freeze the queue until we get 2205265236Sken * a command that completed without this error, which will 2206265236Sken * hopefully have some chain frames attached that we can 2207265236Sken * use. If we wanted to get smarter about it, we would 2208265236Sken * only unfreeze the queue in this condition when we're 2209265236Sken * sure that we're getting some chain frames back. That's 2210265236Sken * probably unnecessary. 2211265236Sken */ 2212265236Sken if ((sassc->flags & MPRSAS_QUEUE_FROZEN) == 0) { 2213265236Sken xpt_freeze_simq(sassc->sim, 1); 2214265236Sken sassc->flags |= MPRSAS_QUEUE_FROZEN; 2215265236Sken mpr_dprint(sc, MPR_INFO, "Error sending command, " 2216265236Sken "freezing SIM queue\n"); 2217265236Sken } 2218265236Sken } 2219265236Sken 2220265236Sken /* 2221265236Sken * If this is a Start Stop Unit command and it was issued by the driver 2222265236Sken * during shutdown, decrement the refcount to account for all of the 2223265236Sken * commands that were sent. All SSU commands should be completed before 2224265236Sken * shutdown completes, meaning SSU_refcount will be 0 after SSU_started 2225265236Sken * is TRUE. 2226265236Sken */ 2227265236Sken if (sc->SSU_started && (csio->cdb_io.cdb_bytes[0] == START_STOP_UNIT)) { 2228265236Sken mpr_dprint(sc, MPR_INFO, "Decrementing SSU count.\n"); 2229265236Sken sc->SSU_refcount--; 2230265236Sken } 2231265236Sken 2232265236Sken /* Take the fast path to completion */ 2233265236Sken if (cm->cm_reply == NULL) { 2234265236Sken if ((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_INPROG) { 2235265236Sken if ((sc->mpr_flags & MPR_FLAGS_DIAGRESET) != 0) 2236265236Sken ccb->ccb_h.status = CAM_SCSI_BUS_RESET; 2237265236Sken else { 2238265236Sken ccb->ccb_h.status = CAM_REQ_CMP; 2239265236Sken ccb->csio.scsi_status = SCSI_STATUS_OK; 2240265236Sken } 2241265236Sken if (sassc->flags & MPRSAS_QUEUE_FROZEN) { 2242265236Sken ccb->ccb_h.status |= CAM_RELEASE_SIMQ; 2243265236Sken sassc->flags &= ~MPRSAS_QUEUE_FROZEN; 2244265236Sken mpr_dprint(sc, MPR_XINFO, 2245265236Sken "Unfreezing SIM queue\n"); 2246265236Sken } 2247265236Sken } 2248265236Sken 2249265236Sken /* 2250265236Sken * There are two scenarios where the status won't be 2251265236Sken * CAM_REQ_CMP. The first is if MPR_CM_FLAGS_ERROR_MASK is 2252265236Sken * set, the second is in the MPR_FLAGS_DIAGRESET above. 2253265236Sken */ 2254265236Sken if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) { 2255265236Sken /* 2256265236Sken * Freeze the dev queue so that commands are 2257265236Sken * executed in the correct order with after error 2258265236Sken * recovery. 2259265236Sken */ 2260265236Sken ccb->ccb_h.status |= CAM_DEV_QFRZN; 2261265236Sken xpt_freeze_devq(ccb->ccb_h.path, /*count*/ 1); 2262265236Sken } 2263265236Sken mpr_free_command(sc, cm); 2264265236Sken xpt_done(ccb); 2265265236Sken return; 2266265236Sken } 2267265236Sken 2268265236Sken mprsas_log_command(cm, MPR_XINFO, 2269265236Sken "ioc %x scsi %x state %x xfer %u\n", 2270265236Sken le16toh(rep->IOCStatus), rep->SCSIStatus, rep->SCSIState, 2271265236Sken le32toh(rep->TransferCount)); 2272265236Sken 2273265236Sken switch (le16toh(rep->IOCStatus) & MPI2_IOCSTATUS_MASK) { 2274265236Sken case MPI2_IOCSTATUS_SCSI_DATA_UNDERRUN: 2275265236Sken csio->resid = cm->cm_length - le32toh(rep->TransferCount); 2276265236Sken /* FALLTHROUGH */ 2277265236Sken case MPI2_IOCSTATUS_SUCCESS: 2278265236Sken case MPI2_IOCSTATUS_SCSI_RECOVERED_ERROR: 2279265236Sken 2280265236Sken if ((le16toh(rep->IOCStatus) & MPI2_IOCSTATUS_MASK) == 2281265236Sken MPI2_IOCSTATUS_SCSI_RECOVERED_ERROR) 2282265236Sken mprsas_log_command(cm, MPR_XINFO, "recovered error\n"); 2283265236Sken 2284265236Sken /* Completion failed at the transport level. */ 2285265236Sken if (rep->SCSIState & (MPI2_SCSI_STATE_NO_SCSI_STATUS | 2286265236Sken MPI2_SCSI_STATE_TERMINATED)) { 2287265236Sken ccb->ccb_h.status = CAM_REQ_CMP_ERR; 2288265236Sken break; 2289265236Sken } 2290265236Sken 2291265236Sken /* In a modern packetized environment, an autosense failure 2292265236Sken * implies that there's not much else that can be done to 2293265236Sken * recover the command. 2294265236Sken */ 2295265236Sken if (rep->SCSIState & MPI2_SCSI_STATE_AUTOSENSE_FAILED) { 2296265236Sken ccb->ccb_h.status = CAM_AUTOSENSE_FAIL; 2297265236Sken break; 2298265236Sken } 2299265236Sken 2300265236Sken /* 2301265236Sken * CAM doesn't care about SAS Response Info data, but if this is 2302265236Sken * the state check if TLR should be done. If not, clear the 2303265236Sken * TLR_bits for the target. 2304265236Sken */ 2305265236Sken if ((rep->SCSIState & MPI2_SCSI_STATE_RESPONSE_INFO_VALID) && 2306265236Sken ((le32toh(rep->ResponseInfo) & MPI2_SCSI_RI_MASK_REASONCODE) 2307265236Sken == MPR_SCSI_RI_INVALID_FRAME)) { 2308265236Sken sc->mapping_table[csio->ccb_h.target_id].TLR_bits = 2309265236Sken (u8)MPI2_SCSIIO_CONTROL_NO_TLR; 2310265236Sken } 2311265236Sken 2312265236Sken /* 2313265236Sken * Intentionally override the normal SCSI status reporting 2314265236Sken * for these two cases. These are likely to happen in a 2315265236Sken * multi-initiator environment, and we want to make sure that 2316265236Sken * CAM retries these commands rather than fail them. 2317265236Sken */ 2318265236Sken if ((rep->SCSIStatus == MPI2_SCSI_STATUS_COMMAND_TERMINATED) || 2319265236Sken (rep->SCSIStatus == MPI2_SCSI_STATUS_TASK_ABORTED)) { 2320265236Sken ccb->ccb_h.status = CAM_REQ_ABORTED; 2321265236Sken break; 2322265236Sken } 2323265236Sken 2324265236Sken /* Handle normal status and sense */ 2325265236Sken csio->scsi_status = rep->SCSIStatus; 2326265236Sken if (rep->SCSIStatus == MPI2_SCSI_STATUS_GOOD) 2327265236Sken ccb->ccb_h.status = CAM_REQ_CMP; 2328265236Sken else 2329265236Sken ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR; 2330265236Sken 2331265236Sken if (rep->SCSIState & MPI2_SCSI_STATE_AUTOSENSE_VALID) { 2332265236Sken int sense_len, returned_sense_len; 2333265236Sken 2334265236Sken returned_sense_len = min(le32toh(rep->SenseCount), 2335265236Sken sizeof(struct scsi_sense_data)); 2336265236Sken if (returned_sense_len < csio->sense_len) 2337265236Sken csio->sense_resid = csio->sense_len - 2338265236Sken returned_sense_len; 2339265236Sken else 2340265236Sken csio->sense_resid = 0; 2341265236Sken 2342265236Sken sense_len = min(returned_sense_len, 2343265236Sken csio->sense_len - csio->sense_resid); 2344265236Sken bzero(&csio->sense_data, sizeof(csio->sense_data)); 2345265236Sken bcopy(cm->cm_sense, &csio->sense_data, sense_len); 2346265236Sken ccb->ccb_h.status |= CAM_AUTOSNS_VALID; 2347265236Sken } 2348265236Sken 2349265236Sken /* 2350265236Sken * Check if this is an INQUIRY command. If it's a VPD inquiry, 2351265236Sken * and it's page code 0 (Supported Page List), and there is 2352265236Sken * inquiry data, and this is for a sequential access device, and 2353265236Sken * the device is an SSP target, and TLR is supported by the 2354265236Sken * controller, turn the TLR_bits value ON if page 0x90 is 2355265236Sken * supported. 2356265236Sken */ 2357265236Sken if ((csio->cdb_io.cdb_bytes[0] == INQUIRY) && 2358265236Sken (csio->cdb_io.cdb_bytes[1] & SI_EVPD) && 2359265236Sken (csio->cdb_io.cdb_bytes[2] == SVPD_SUPPORTED_PAGE_LIST) && 2360265236Sken ((csio->ccb_h.flags & CAM_DATA_MASK) == CAM_DATA_VADDR) && 2361266549Sken (csio->data_ptr != NULL) && 2362266549Sken ((csio->data_ptr[0] & 0x1f) == T_SEQUENTIAL) && 2363266549Sken (sc->control_TLR) && 2364265236Sken (sc->mapping_table[csio->ccb_h.target_id].device_info & 2365265236Sken MPI2_SAS_DEVICE_INFO_SSP_TARGET)) { 2366265236Sken vpd_list = (struct scsi_vpd_supported_page_list *) 2367265236Sken csio->data_ptr; 2368265236Sken TLR_bits = &sc->mapping_table[csio->ccb_h.target_id]. 2369265236Sken TLR_bits; 2370265236Sken *TLR_bits = (u8)MPI2_SCSIIO_CONTROL_NO_TLR; 2371265236Sken TLR_on = (u8)MPI2_SCSIIO_CONTROL_TLR_ON; 2372265236Sken alloc_len = ((u16)csio->cdb_io.cdb_bytes[3] << 8) + 2373265236Sken csio->cdb_io.cdb_bytes[4]; 2374266549Sken alloc_len -= csio->resid; 2375265236Sken for (i = 0; i < MIN(vpd_list->length, alloc_len); i++) { 2376265236Sken if (vpd_list->list[i] == 0x90) { 2377265236Sken *TLR_bits = TLR_on; 2378265236Sken break; 2379265236Sken } 2380265236Sken } 2381265236Sken } 2382265236Sken break; 2383265236Sken case MPI2_IOCSTATUS_SCSI_INVALID_DEVHANDLE: 2384265236Sken case MPI2_IOCSTATUS_SCSI_DEVICE_NOT_THERE: 2385265236Sken /* 2386265236Sken * If devinfo is 0 this will be a volume. In that case don't 2387265236Sken * tell CAM that the volume is not there. We want volumes to 2388265236Sken * be enumerated until they are deleted/removed, not just 2389265236Sken * failed. 2390265236Sken */ 2391265236Sken if (cm->cm_targ->devinfo == 0) 2392265236Sken ccb->ccb_h.status = CAM_REQ_CMP; 2393265236Sken else 2394265236Sken ccb->ccb_h.status = CAM_DEV_NOT_THERE; 2395265236Sken break; 2396265236Sken case MPI2_IOCSTATUS_INVALID_SGL: 2397265236Sken mpr_print_scsiio_cmd(sc, cm); 2398265236Sken ccb->ccb_h.status = CAM_UNREC_HBA_ERROR; 2399265236Sken break; 2400265236Sken case MPI2_IOCSTATUS_SCSI_TASK_TERMINATED: 2401265236Sken /* 2402265236Sken * This is one of the responses that comes back when an I/O 2403265236Sken * has been aborted. If it is because of a timeout that we 2404265236Sken * initiated, just set the status to CAM_CMD_TIMEOUT. 2405265236Sken * Otherwise set it to CAM_REQ_ABORTED. The effect on the 2406265236Sken * command is the same (it gets retried, subject to the 2407265236Sken * retry counter), the only difference is what gets printed 2408265236Sken * on the console. 2409265236Sken */ 2410265236Sken if (cm->cm_state == MPR_CM_STATE_TIMEDOUT) 2411265236Sken ccb->ccb_h.status = CAM_CMD_TIMEOUT; 2412265236Sken else 2413265236Sken ccb->ccb_h.status = CAM_REQ_ABORTED; 2414265236Sken break; 2415265236Sken case MPI2_IOCSTATUS_SCSI_DATA_OVERRUN: 2416265236Sken /* resid is ignored for this condition */ 2417265236Sken csio->resid = 0; 2418265236Sken ccb->ccb_h.status = CAM_DATA_RUN_ERR; 2419265236Sken break; 2420265236Sken case MPI2_IOCSTATUS_SCSI_IOC_TERMINATED: 2421265236Sken case MPI2_IOCSTATUS_SCSI_EXT_TERMINATED: 2422265236Sken /* 2423265236Sken * Since these are generally external (i.e. hopefully 2424265236Sken * transient transport-related) errors, retry these without 2425265236Sken * decrementing the retry count. 2426265236Sken */ 2427265236Sken ccb->ccb_h.status = CAM_REQUEUE_REQ; 2428265236Sken mprsas_log_command(cm, MPR_INFO, 2429265236Sken "terminated ioc %x scsi %x state %x xfer %u\n", 2430265236Sken le16toh(rep->IOCStatus), rep->SCSIStatus, rep->SCSIState, 2431265236Sken le32toh(rep->TransferCount)); 2432265236Sken break; 2433265236Sken case MPI2_IOCSTATUS_INVALID_FUNCTION: 2434265236Sken case MPI2_IOCSTATUS_INTERNAL_ERROR: 2435265236Sken case MPI2_IOCSTATUS_INVALID_VPID: 2436265236Sken case MPI2_IOCSTATUS_INVALID_FIELD: 2437265236Sken case MPI2_IOCSTATUS_INVALID_STATE: 2438265236Sken case MPI2_IOCSTATUS_OP_STATE_NOT_SUPPORTED: 2439265236Sken case MPI2_IOCSTATUS_SCSI_IO_DATA_ERROR: 2440265236Sken case MPI2_IOCSTATUS_SCSI_PROTOCOL_ERROR: 2441265236Sken case MPI2_IOCSTATUS_SCSI_RESIDUAL_MISMATCH: 2442265236Sken case MPI2_IOCSTATUS_SCSI_TASK_MGMT_FAILED: 2443265236Sken default: 2444265236Sken mprsas_log_command(cm, MPR_XINFO, 2445265236Sken "completed ioc %x scsi %x state %x xfer %u\n", 2446265236Sken le16toh(rep->IOCStatus), rep->SCSIStatus, rep->SCSIState, 2447265236Sken le32toh(rep->TransferCount)); 2448265236Sken csio->resid = cm->cm_length; 2449265236Sken ccb->ccb_h.status = CAM_REQ_CMP_ERR; 2450265236Sken break; 2451265236Sken } 2452265236Sken 2453265236Sken mpr_sc_failed_io_info(sc, csio, rep, cm->cm_targ); 2454265236Sken 2455265236Sken if (sassc->flags & MPRSAS_QUEUE_FROZEN) { 2456265236Sken ccb->ccb_h.status |= CAM_RELEASE_SIMQ; 2457265236Sken sassc->flags &= ~MPRSAS_QUEUE_FROZEN; 2458265236Sken mpr_dprint(sc, MPR_XINFO, "Command completed, unfreezing SIM " 2459265236Sken "queue\n"); 2460265236Sken } 2461265236Sken 2462265236Sken if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) { 2463265236Sken ccb->ccb_h.status |= CAM_DEV_QFRZN; 2464265236Sken xpt_freeze_devq(ccb->ccb_h.path, /*count*/ 1); 2465265236Sken } 2466265236Sken 2467265236Sken mpr_free_command(sc, cm); 2468265236Sken xpt_done(ccb); 2469265236Sken} 2470265236Sken 2471265236Sken#if __FreeBSD_version >= 900026 2472265236Skenstatic void 2473265236Skenmprsas_smpio_complete(struct mpr_softc *sc, struct mpr_command *cm) 2474265236Sken{ 2475265236Sken MPI2_SMP_PASSTHROUGH_REPLY *rpl; 2476265236Sken MPI2_SMP_PASSTHROUGH_REQUEST *req; 2477265236Sken uint64_t sasaddr; 2478265236Sken union ccb *ccb; 2479265236Sken 2480265236Sken ccb = cm->cm_complete_data; 2481265236Sken 2482265236Sken /* 2483265236Sken * Currently there should be no way we can hit this case. It only 2484265236Sken * happens when we have a failure to allocate chain frames, and SMP 2485265236Sken * commands require two S/G elements only. That should be handled 2486265236Sken * in the standard request size. 2487265236Sken */ 2488265236Sken if ((cm->cm_flags & MPR_CM_FLAGS_ERROR_MASK) != 0) { 2489265236Sken mpr_dprint(sc, MPR_ERROR,"%s: cm_flags = %#x on SMP request!\n", 2490265236Sken __func__, cm->cm_flags); 2491265236Sken ccb->ccb_h.status = CAM_REQ_CMP_ERR; 2492265236Sken goto bailout; 2493265236Sken } 2494265236Sken 2495265236Sken rpl = (MPI2_SMP_PASSTHROUGH_REPLY *)cm->cm_reply; 2496265236Sken if (rpl == NULL) { 2497265236Sken mpr_dprint(sc, MPR_ERROR, "%s: NULL cm_reply!\n", __func__); 2498265236Sken ccb->ccb_h.status = CAM_REQ_CMP_ERR; 2499265236Sken goto bailout; 2500265236Sken } 2501265236Sken 2502265236Sken req = (MPI2_SMP_PASSTHROUGH_REQUEST *)cm->cm_req; 2503265236Sken sasaddr = le32toh(req->SASAddress.Low); 2504265236Sken sasaddr |= ((uint64_t)(le32toh(req->SASAddress.High))) << 32; 2505265236Sken 2506265236Sken if ((le16toh(rpl->IOCStatus) & MPI2_IOCSTATUS_MASK) != 2507265236Sken MPI2_IOCSTATUS_SUCCESS || 2508265236Sken rpl->SASStatus != MPI2_SASSTATUS_SUCCESS) { 2509265236Sken mpr_dprint(sc, MPR_XINFO, "%s: IOCStatus %04x SASStatus %02x\n", 2510265236Sken __func__, le16toh(rpl->IOCStatus), rpl->SASStatus); 2511265236Sken ccb->ccb_h.status = CAM_REQ_CMP_ERR; 2512265236Sken goto bailout; 2513265236Sken } 2514265236Sken 2515265236Sken mpr_dprint(sc, MPR_XINFO, "%s: SMP request to SAS address " 2516265236Sken "%#jx completed successfully\n", __func__, (uintmax_t)sasaddr); 2517265236Sken 2518265236Sken if (ccb->smpio.smp_response[2] == SMP_FR_ACCEPTED) 2519265236Sken ccb->ccb_h.status = CAM_REQ_CMP; 2520265236Sken else 2521265236Sken ccb->ccb_h.status = CAM_SMP_STATUS_ERROR; 2522265236Sken 2523265236Skenbailout: 2524265236Sken /* 2525265236Sken * We sync in both directions because we had DMAs in the S/G list 2526265236Sken * in both directions. 2527265236Sken */ 2528265236Sken bus_dmamap_sync(sc->buffer_dmat, cm->cm_dmamap, 2529265236Sken BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); 2530265236Sken bus_dmamap_unload(sc->buffer_dmat, cm->cm_dmamap); 2531265236Sken mpr_free_command(sc, cm); 2532265236Sken xpt_done(ccb); 2533265236Sken} 2534265236Sken 2535265236Skenstatic void 2536265236Skenmprsas_send_smpcmd(struct mprsas_softc *sassc, union ccb *ccb, 2537265236Sken uint64_t sasaddr) 2538265236Sken{ 2539265236Sken struct mpr_command *cm; 2540265236Sken uint8_t *request, *response; 2541265236Sken MPI2_SMP_PASSTHROUGH_REQUEST *req; 2542265236Sken struct mpr_softc *sc; 2543265236Sken struct sglist *sg; 2544265236Sken int error; 2545265236Sken 2546265236Sken sc = sassc->sc; 2547265236Sken sg = NULL; 2548265236Sken error = 0; 2549265236Sken 2550265729Sken#if (__FreeBSD_version >= 1000028) || \ 2551265729Sken ((__FreeBSD_version >= 902001) && (__FreeBSD_version < 1000000)) 2552265236Sken switch (ccb->ccb_h.flags & CAM_DATA_MASK) { 2553265236Sken case CAM_DATA_PADDR: 2554265236Sken case CAM_DATA_SG_PADDR: 2555265236Sken /* 2556265236Sken * XXX We don't yet support physical addresses here. 2557265236Sken */ 2558265236Sken mpr_dprint(sc, MPR_ERROR, "%s: physical addresses not " 2559265236Sken "supported\n", __func__); 2560265236Sken ccb->ccb_h.status = CAM_REQ_INVALID; 2561265236Sken xpt_done(ccb); 2562265236Sken return; 2563265236Sken case CAM_DATA_SG: 2564265236Sken /* 2565265236Sken * The chip does not support more than one buffer for the 2566265236Sken * request or response. 2567265236Sken */ 2568265236Sken if ((ccb->smpio.smp_request_sglist_cnt > 1) 2569265236Sken || (ccb->smpio.smp_response_sglist_cnt > 1)) { 2570265236Sken mpr_dprint(sc, MPR_ERROR, 2571265236Sken "%s: multiple request or response buffer segments " 2572265236Sken "not supported for SMP\n", __func__); 2573265236Sken ccb->ccb_h.status = CAM_REQ_INVALID; 2574265236Sken xpt_done(ccb); 2575265236Sken return; 2576265236Sken } 2577265236Sken 2578265236Sken /* 2579265236Sken * The CAM_SCATTER_VALID flag was originally implemented 2580265236Sken * for the XPT_SCSI_IO CCB, which only has one data pointer. 2581265236Sken * We have two. So, just take that flag to mean that we 2582265236Sken * might have S/G lists, and look at the S/G segment count 2583265236Sken * to figure out whether that is the case for each individual 2584265236Sken * buffer. 2585265236Sken */ 2586265236Sken if (ccb->smpio.smp_request_sglist_cnt != 0) { 2587265236Sken bus_dma_segment_t *req_sg; 2588265236Sken 2589265236Sken req_sg = (bus_dma_segment_t *)ccb->smpio.smp_request; 2590265236Sken request = (uint8_t *)(uintptr_t)req_sg[0].ds_addr; 2591265236Sken } else 2592265236Sken request = ccb->smpio.smp_request; 2593265236Sken 2594265236Sken if (ccb->smpio.smp_response_sglist_cnt != 0) { 2595265236Sken bus_dma_segment_t *rsp_sg; 2596265236Sken 2597265236Sken rsp_sg = (bus_dma_segment_t *)ccb->smpio.smp_response; 2598265236Sken response = (uint8_t *)(uintptr_t)rsp_sg[0].ds_addr; 2599265236Sken } else 2600265236Sken response = ccb->smpio.smp_response; 2601265236Sken break; 2602265236Sken case CAM_DATA_VADDR: 2603265236Sken request = ccb->smpio.smp_request; 2604265236Sken response = ccb->smpio.smp_response; 2605265236Sken break; 2606265236Sken default: 2607265236Sken ccb->ccb_h.status = CAM_REQ_INVALID; 2608265236Sken xpt_done(ccb); 2609265236Sken return; 2610265236Sken } 2611265729Sken#else /* __FreeBSD_version < 1000028 */ 2612265236Sken /* 2613265236Sken * XXX We don't yet support physical addresses here. 2614265236Sken */ 2615265236Sken if (ccb->ccb_h.flags & (CAM_DATA_PHYS|CAM_SG_LIST_PHYS)) { 2616265236Sken mpr_printf(sc, "%s: physical addresses not supported\n", 2617265236Sken __func__); 2618265236Sken ccb->ccb_h.status = CAM_REQ_INVALID; 2619265236Sken xpt_done(ccb); 2620265236Sken return; 2621265236Sken } 2622265236Sken 2623265236Sken /* 2624265236Sken * If the user wants to send an S/G list, check to make sure they 2625265236Sken * have single buffers. 2626265236Sken */ 2627265236Sken if (ccb->ccb_h.flags & CAM_SCATTER_VALID) { 2628265236Sken /* 2629265236Sken * The chip does not support more than one buffer for the 2630265236Sken * request or response. 2631265236Sken */ 2632265236Sken if ((ccb->smpio.smp_request_sglist_cnt > 1) 2633265236Sken || (ccb->smpio.smp_response_sglist_cnt > 1)) { 2634265236Sken mpr_dprint(sc, MPR_ERROR, "%s: multiple request or " 2635265236Sken "response buffer segments not supported for SMP\n", 2636265236Sken __func__); 2637265236Sken ccb->ccb_h.status = CAM_REQ_INVALID; 2638265236Sken xpt_done(ccb); 2639265236Sken return; 2640265236Sken } 2641265236Sken 2642265236Sken /* 2643265236Sken * The CAM_SCATTER_VALID flag was originally implemented 2644265236Sken * for the XPT_SCSI_IO CCB, which only has one data pointer. 2645265236Sken * We have two. So, just take that flag to mean that we 2646265236Sken * might have S/G lists, and look at the S/G segment count 2647265236Sken * to figure out whether that is the case for each individual 2648265236Sken * buffer. 2649265236Sken */ 2650265236Sken if (ccb->smpio.smp_request_sglist_cnt != 0) { 2651265236Sken bus_dma_segment_t *req_sg; 2652265236Sken 2653265236Sken req_sg = (bus_dma_segment_t *)ccb->smpio.smp_request; 2654265729Sken request = (uint8_t *)(uintptr_t)req_sg[0].ds_addr; 2655265236Sken } else 2656265236Sken request = ccb->smpio.smp_request; 2657265236Sken 2658265236Sken if (ccb->smpio.smp_response_sglist_cnt != 0) { 2659265236Sken bus_dma_segment_t *rsp_sg; 2660265236Sken 2661265236Sken rsp_sg = (bus_dma_segment_t *)ccb->smpio.smp_response; 2662265729Sken response = (uint8_t *)(uintptr_t)rsp_sg[0].ds_addr; 2663265236Sken } else 2664265236Sken response = ccb->smpio.smp_response; 2665265236Sken } else { 2666265236Sken request = ccb->smpio.smp_request; 2667265236Sken response = ccb->smpio.smp_response; 2668265236Sken } 2669265729Sken#endif /* __FreeBSD_version < 1000028 */ 2670265236Sken 2671265236Sken cm = mpr_alloc_command(sc); 2672265236Sken if (cm == NULL) { 2673265236Sken mpr_dprint(sc, MPR_ERROR, 2674265236Sken "%s: cannot allocate command\n", __func__); 2675265236Sken ccb->ccb_h.status = CAM_RESRC_UNAVAIL; 2676265236Sken xpt_done(ccb); 2677265236Sken return; 2678265236Sken } 2679265236Sken 2680265236Sken req = (MPI2_SMP_PASSTHROUGH_REQUEST *)cm->cm_req; 2681265236Sken bzero(req, sizeof(*req)); 2682265236Sken req->Function = MPI2_FUNCTION_SMP_PASSTHROUGH; 2683265236Sken 2684265236Sken /* Allow the chip to use any route to this SAS address. */ 2685265236Sken req->PhysicalPort = 0xff; 2686265236Sken 2687265236Sken req->RequestDataLength = htole16(ccb->smpio.smp_request_len); 2688265236Sken req->SGLFlags = 2689265236Sken MPI2_SGLFLAGS_SYSTEM_ADDRESS_SPACE | MPI2_SGLFLAGS_SGL_TYPE_MPI; 2690265236Sken 2691265236Sken mpr_dprint(sc, MPR_XINFO, "%s: sending SMP request to SAS address " 2692265236Sken "%#jx\n", __func__, (uintmax_t)sasaddr); 2693265236Sken 2694265236Sken mpr_init_sge(cm, req, &req->SGL); 2695265236Sken 2696265236Sken /* 2697265236Sken * Set up a uio to pass into mpr_map_command(). This allows us to 2698265236Sken * do one map command, and one busdma call in there. 2699265236Sken */ 2700265236Sken cm->cm_uio.uio_iov = cm->cm_iovec; 2701265236Sken cm->cm_uio.uio_iovcnt = 2; 2702265236Sken cm->cm_uio.uio_segflg = UIO_SYSSPACE; 2703265236Sken 2704265236Sken /* 2705265236Sken * The read/write flag isn't used by busdma, but set it just in 2706265236Sken * case. This isn't exactly accurate, either, since we're going in 2707265236Sken * both directions. 2708265236Sken */ 2709265236Sken cm->cm_uio.uio_rw = UIO_WRITE; 2710265236Sken 2711265236Sken cm->cm_iovec[0].iov_base = request; 2712265236Sken cm->cm_iovec[0].iov_len = le16toh(req->RequestDataLength); 2713265236Sken cm->cm_iovec[1].iov_base = response; 2714265236Sken cm->cm_iovec[1].iov_len = ccb->smpio.smp_response_len; 2715265236Sken 2716265236Sken cm->cm_uio.uio_resid = cm->cm_iovec[0].iov_len + 2717265236Sken cm->cm_iovec[1].iov_len; 2718265236Sken 2719265236Sken /* 2720265236Sken * Trigger a warning message in mpr_data_cb() for the user if we 2721265236Sken * wind up exceeding two S/G segments. The chip expects one 2722265236Sken * segment for the request and another for the response. 2723265236Sken */ 2724265236Sken cm->cm_max_segs = 2; 2725265236Sken 2726265236Sken cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 2727265236Sken cm->cm_complete = mprsas_smpio_complete; 2728265236Sken cm->cm_complete_data = ccb; 2729265236Sken 2730265236Sken /* 2731265236Sken * Tell the mapping code that we're using a uio, and that this is 2732265236Sken * an SMP passthrough request. There is a little special-case 2733265236Sken * logic there (in mpr_data_cb()) to handle the bidirectional 2734265236Sken * transfer. 2735265236Sken */ 2736265236Sken cm->cm_flags |= MPR_CM_FLAGS_USE_UIO | MPR_CM_FLAGS_SMP_PASS | 2737265236Sken MPR_CM_FLAGS_DATAIN | MPR_CM_FLAGS_DATAOUT; 2738265236Sken 2739265236Sken /* The chip data format is little endian. */ 2740265236Sken req->SASAddress.High = htole32(sasaddr >> 32); 2741265236Sken req->SASAddress.Low = htole32(sasaddr); 2742265236Sken 2743265236Sken /* 2744265236Sken * XXX Note that we don't have a timeout/abort mechanism here. 2745265236Sken * From the manual, it looks like task management requests only 2746265236Sken * work for SCSI IO and SATA passthrough requests. We may need to 2747265236Sken * have a mechanism to retry requests in the event of a chip reset 2748265236Sken * at least. Hopefully the chip will insure that any errors short 2749265236Sken * of that are relayed back to the driver. 2750265236Sken */ 2751265236Sken error = mpr_map_command(sc, cm); 2752265236Sken if ((error != 0) && (error != EINPROGRESS)) { 2753265236Sken mpr_dprint(sc, MPR_ERROR, "%s: error %d returned from " 2754265236Sken "mpr_map_command()\n", __func__, error); 2755265236Sken goto bailout_error; 2756265236Sken } 2757265236Sken 2758265236Sken return; 2759265236Sken 2760265236Skenbailout_error: 2761265236Sken mpr_free_command(sc, cm); 2762265236Sken ccb->ccb_h.status = CAM_RESRC_UNAVAIL; 2763265236Sken xpt_done(ccb); 2764265236Sken return; 2765265236Sken} 2766265236Sken 2767265236Skenstatic void 2768265236Skenmprsas_action_smpio(struct mprsas_softc *sassc, union ccb *ccb) 2769265236Sken{ 2770265236Sken struct mpr_softc *sc; 2771265236Sken struct mprsas_target *targ; 2772265236Sken uint64_t sasaddr = 0; 2773265236Sken 2774265236Sken sc = sassc->sc; 2775265236Sken 2776265236Sken /* 2777265236Sken * Make sure the target exists. 2778265236Sken */ 2779265236Sken KASSERT(ccb->ccb_h.target_id < sassc->maxtargets, 2780265236Sken ("Target %d out of bounds in XPT_SMP_IO\n", ccb->ccb_h.target_id)); 2781265236Sken targ = &sassc->targets[ccb->ccb_h.target_id]; 2782265236Sken if (targ->handle == 0x0) { 2783265236Sken mpr_dprint(sc, MPR_ERROR, "%s: target %d does not exist!\n", 2784265236Sken __func__, ccb->ccb_h.target_id); 2785265236Sken ccb->ccb_h.status = CAM_SEL_TIMEOUT; 2786265236Sken xpt_done(ccb); 2787265236Sken return; 2788265236Sken } 2789265236Sken 2790265236Sken /* 2791265236Sken * If this device has an embedded SMP target, we'll talk to it 2792265236Sken * directly. 2793265236Sken * figure out what the expander's address is. 2794265236Sken */ 2795265236Sken if ((targ->devinfo & MPI2_SAS_DEVICE_INFO_SMP_TARGET) != 0) 2796265236Sken sasaddr = targ->sasaddr; 2797265236Sken 2798265236Sken /* 2799265236Sken * If we don't have a SAS address for the expander yet, try 2800265236Sken * grabbing it from the page 0x83 information cached in the 2801265236Sken * transport layer for this target. LSI expanders report the 2802265236Sken * expander SAS address as the port-associated SAS address in 2803265236Sken * Inquiry VPD page 0x83. Maxim expanders don't report it in page 2804265236Sken * 0x83. 2805265236Sken * 2806265236Sken * XXX KDM disable this for now, but leave it commented out so that 2807265236Sken * it is obvious that this is another possible way to get the SAS 2808265236Sken * address. 2809265236Sken * 2810265236Sken * The parent handle method below is a little more reliable, and 2811265236Sken * the other benefit is that it works for devices other than SES 2812265236Sken * devices. So you can send a SMP request to a da(4) device and it 2813265236Sken * will get routed to the expander that device is attached to. 2814265236Sken * (Assuming the da(4) device doesn't contain an SMP target...) 2815265236Sken */ 2816265236Sken#if 0 2817265236Sken if (sasaddr == 0) 2818265236Sken sasaddr = xpt_path_sas_addr(ccb->ccb_h.path); 2819265236Sken#endif 2820265236Sken 2821265236Sken /* 2822265236Sken * If we still don't have a SAS address for the expander, look for 2823265236Sken * the parent device of this device, which is probably the expander. 2824265236Sken */ 2825265236Sken if (sasaddr == 0) { 2826265236Sken#ifdef OLD_MPR_PROBE 2827265236Sken struct mprsas_target *parent_target; 2828265236Sken#endif 2829265236Sken 2830265236Sken if (targ->parent_handle == 0x0) { 2831265236Sken mpr_dprint(sc, MPR_ERROR, "%s: handle %d does not have " 2832265236Sken "a valid parent handle!\n", __func__, targ->handle); 2833265236Sken ccb->ccb_h.status = CAM_DEV_NOT_THERE; 2834265236Sken goto bailout; 2835265236Sken } 2836265236Sken#ifdef OLD_MPR_PROBE 2837265236Sken parent_target = mprsas_find_target_by_handle(sassc, 0, 2838265236Sken targ->parent_handle); 2839265236Sken 2840265236Sken if (parent_target == NULL) { 2841265236Sken mpr_dprint(sc, MPR_ERROR, "%s: handle %d does not have " 2842265236Sken "a valid parent target!\n", __func__, targ->handle); 2843265236Sken ccb->ccb_h.status = CAM_DEV_NOT_THERE; 2844265236Sken goto bailout; 2845265236Sken } 2846265236Sken 2847265236Sken if ((parent_target->devinfo & 2848265236Sken MPI2_SAS_DEVICE_INFO_SMP_TARGET) == 0) { 2849265236Sken mpr_dprint(sc, MPR_ERROR, "%s: handle %d parent %d " 2850265236Sken "does not have an SMP target!\n", __func__, 2851265236Sken targ->handle, parent_target->handle); 2852265236Sken ccb->ccb_h.status = CAM_DEV_NOT_THERE; 2853265236Sken goto bailout; 2854265236Sken 2855265236Sken } 2856265236Sken 2857265236Sken sasaddr = parent_target->sasaddr; 2858265236Sken#else /* OLD_MPR_PROBE */ 2859265236Sken if ((targ->parent_devinfo & 2860265236Sken MPI2_SAS_DEVICE_INFO_SMP_TARGET) == 0) { 2861265236Sken mpr_dprint(sc, MPR_ERROR, "%s: handle %d parent %d " 2862265236Sken "does not have an SMP target!\n", __func__, 2863265236Sken targ->handle, targ->parent_handle); 2864265236Sken ccb->ccb_h.status = CAM_DEV_NOT_THERE; 2865265236Sken goto bailout; 2866265236Sken 2867265236Sken } 2868265236Sken if (targ->parent_sasaddr == 0x0) { 2869265236Sken mpr_dprint(sc, MPR_ERROR, "%s: handle %d parent handle " 2870265236Sken "%d does not have a valid SAS address!\n", __func__, 2871265236Sken targ->handle, targ->parent_handle); 2872265236Sken ccb->ccb_h.status = CAM_DEV_NOT_THERE; 2873265236Sken goto bailout; 2874265236Sken } 2875265236Sken 2876265236Sken sasaddr = targ->parent_sasaddr; 2877265236Sken#endif /* OLD_MPR_PROBE */ 2878265236Sken 2879265236Sken } 2880265236Sken 2881265236Sken if (sasaddr == 0) { 2882265236Sken mpr_dprint(sc, MPR_INFO, "%s: unable to find SAS address for " 2883265236Sken "handle %d\n", __func__, targ->handle); 2884265236Sken ccb->ccb_h.status = CAM_DEV_NOT_THERE; 2885265236Sken goto bailout; 2886265236Sken } 2887265236Sken mprsas_send_smpcmd(sassc, ccb, sasaddr); 2888265236Sken 2889265236Sken return; 2890265236Sken 2891265236Skenbailout: 2892265236Sken xpt_done(ccb); 2893265236Sken 2894265236Sken} 2895265236Sken#endif //__FreeBSD_version >= 900026 2896265236Sken 2897265236Skenstatic void 2898265236Skenmprsas_action_resetdev(struct mprsas_softc *sassc, union ccb *ccb) 2899265236Sken{ 2900265236Sken MPI2_SCSI_TASK_MANAGE_REQUEST *req; 2901265236Sken struct mpr_softc *sc; 2902265236Sken struct mpr_command *tm; 2903265236Sken struct mprsas_target *targ; 2904265236Sken 2905265236Sken MPR_FUNCTRACE(sassc->sc); 2906265236Sken mtx_assert(&sassc->sc->mpr_mtx, MA_OWNED); 2907265236Sken 2908265236Sken KASSERT(ccb->ccb_h.target_id < sassc->maxtargets, 2909265236Sken ("Target %d out of bounds in XPT_RESET_DEV\n", 2910265236Sken ccb->ccb_h.target_id)); 2911265236Sken sc = sassc->sc; 2912265236Sken tm = mpr_alloc_command(sc); 2913265236Sken if (tm == NULL) { 2914265236Sken mpr_dprint(sc, MPR_ERROR, 2915265236Sken "command alloc failure in mprsas_action_resetdev\n"); 2916265236Sken ccb->ccb_h.status = CAM_RESRC_UNAVAIL; 2917265236Sken xpt_done(ccb); 2918265236Sken return; 2919265236Sken } 2920265236Sken 2921265236Sken targ = &sassc->targets[ccb->ccb_h.target_id]; 2922265236Sken req = (MPI2_SCSI_TASK_MANAGE_REQUEST *)tm->cm_req; 2923265236Sken req->DevHandle = htole16(targ->handle); 2924265236Sken req->Function = MPI2_FUNCTION_SCSI_TASK_MGMT; 2925265236Sken req->TaskType = MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET; 2926265236Sken 2927265236Sken /* SAS Hard Link Reset / SATA Link Reset */ 2928265236Sken req->MsgFlags = MPI2_SCSITASKMGMT_MSGFLAGS_LINK_RESET; 2929265236Sken 2930265236Sken tm->cm_data = NULL; 2931265236Sken tm->cm_desc.HighPriority.RequestFlags = 2932265236Sken MPI2_REQ_DESCRIPT_FLAGS_HIGH_PRIORITY; 2933265236Sken tm->cm_complete = mprsas_resetdev_complete; 2934265236Sken tm->cm_complete_data = ccb; 2935265236Sken tm->cm_targ = targ; 2936265236Sken mpr_map_command(sc, tm); 2937265236Sken} 2938265236Sken 2939265236Skenstatic void 2940265236Skenmprsas_resetdev_complete(struct mpr_softc *sc, struct mpr_command *tm) 2941265236Sken{ 2942265236Sken MPI2_SCSI_TASK_MANAGE_REPLY *resp; 2943265236Sken union ccb *ccb; 2944265236Sken 2945265236Sken MPR_FUNCTRACE(sc); 2946265236Sken mtx_assert(&sc->mpr_mtx, MA_OWNED); 2947265236Sken 2948265236Sken resp = (MPI2_SCSI_TASK_MANAGE_REPLY *)tm->cm_reply; 2949265236Sken ccb = tm->cm_complete_data; 2950265236Sken 2951265236Sken /* 2952265236Sken * Currently there should be no way we can hit this case. It only 2953265236Sken * happens when we have a failure to allocate chain frames, and 2954265236Sken * task management commands don't have S/G lists. 2955265236Sken */ 2956265236Sken if ((tm->cm_flags & MPR_CM_FLAGS_ERROR_MASK) != 0) { 2957265236Sken MPI2_SCSI_TASK_MANAGE_REQUEST *req; 2958265236Sken 2959265236Sken req = (MPI2_SCSI_TASK_MANAGE_REQUEST *)tm->cm_req; 2960265236Sken 2961265236Sken mpr_dprint(sc, MPR_ERROR, "%s: cm_flags = %#x for reset of " 2962265236Sken "handle %#04x! This should not happen!\n", __func__, 2963265236Sken tm->cm_flags, req->DevHandle); 2964265236Sken ccb->ccb_h.status = CAM_REQ_CMP_ERR; 2965265236Sken goto bailout; 2966265236Sken } 2967265236Sken 2968265236Sken mpr_dprint(sc, MPR_XINFO, 2969265236Sken "%s: IOCStatus = 0x%x ResponseCode = 0x%x\n", __func__, 2970265236Sken le16toh(resp->IOCStatus), le32toh(resp->ResponseCode)); 2971265236Sken 2972265236Sken if (le32toh(resp->ResponseCode) == MPI2_SCSITASKMGMT_RSP_TM_COMPLETE) { 2973265236Sken ccb->ccb_h.status = CAM_REQ_CMP; 2974265236Sken mprsas_announce_reset(sc, AC_SENT_BDR, tm->cm_targ->tid, 2975265236Sken CAM_LUN_WILDCARD); 2976265236Sken } 2977265236Sken else 2978265236Sken ccb->ccb_h.status = CAM_REQ_CMP_ERR; 2979265236Sken 2980265236Skenbailout: 2981265236Sken 2982265236Sken mprsas_free_tm(sc, tm); 2983265236Sken xpt_done(ccb); 2984265236Sken} 2985265236Sken 2986265236Skenstatic void 2987265236Skenmprsas_poll(struct cam_sim *sim) 2988265236Sken{ 2989265236Sken struct mprsas_softc *sassc; 2990265236Sken 2991265236Sken sassc = cam_sim_softc(sim); 2992265236Sken 2993265236Sken if (sassc->sc->mpr_debug & MPR_TRACE) { 2994265236Sken /* frequent debug messages during a panic just slow 2995265236Sken * everything down too much. 2996265236Sken */ 2997265236Sken mpr_printf(sassc->sc, "%s clearing MPR_TRACE\n", __func__); 2998265236Sken sassc->sc->mpr_debug &= ~MPR_TRACE; 2999265236Sken } 3000265236Sken 3001265236Sken mpr_intr_locked(sassc->sc); 3002265236Sken} 3003265236Sken 3004265236Skenstatic void 3005265236Skenmprsas_async(void *callback_arg, uint32_t code, struct cam_path *path, 3006265236Sken void *arg) 3007265236Sken{ 3008265236Sken struct mpr_softc *sc; 3009265236Sken 3010265236Sken sc = (struct mpr_softc *)callback_arg; 3011265236Sken 3012265236Sken switch (code) { 3013265236Sken#if (__FreeBSD_version >= 1000006) || \ 3014265236Sken ((__FreeBSD_version >= 901503) && (__FreeBSD_version < 1000000)) 3015265236Sken case AC_ADVINFO_CHANGED: { 3016265236Sken struct mprsas_target *target; 3017265236Sken struct mprsas_softc *sassc; 3018265236Sken struct scsi_read_capacity_data_long rcap_buf; 3019265236Sken struct ccb_dev_advinfo cdai; 3020265236Sken struct mprsas_lun *lun; 3021265236Sken lun_id_t lunid; 3022265236Sken int found_lun; 3023265236Sken uintptr_t buftype; 3024265236Sken 3025265236Sken buftype = (uintptr_t)arg; 3026265236Sken 3027265236Sken found_lun = 0; 3028265236Sken sassc = sc->sassc; 3029265236Sken 3030265236Sken /* 3031265236Sken * We're only interested in read capacity data changes. 3032265236Sken */ 3033265236Sken if (buftype != CDAI_TYPE_RCAPLONG) 3034265236Sken break; 3035265236Sken 3036265236Sken /* 3037265729Sken * See the comment in mpr_attach_sas() for a detailed 3038265729Sken * explanation. In these versions of FreeBSD we register 3039265729Sken * for all events and filter out the events that don't 3040265729Sken * apply to us. 3041265729Sken */ 3042265729Sken#if (__FreeBSD_version < 1000703) || \ 3043265729Sken ((__FreeBSD_version >= 1100000) && (__FreeBSD_version < 1100002)) 3044265729Sken if (xpt_path_path_id(path) != sassc->sim->path_id) 3045265729Sken break; 3046265729Sken#endif 3047265729Sken 3048265729Sken /* 3049265236Sken * We should have a handle for this, but check to make sure. 3050265236Sken */ 3051265236Sken KASSERT(xpt_path_target_id(path) < sassc->maxtargets, 3052265236Sken ("Target %d out of bounds in mprsas_async\n", 3053265236Sken xpt_path_target_id(path))); 3054265236Sken target = &sassc->targets[xpt_path_target_id(path)]; 3055265236Sken if (target->handle == 0) 3056265236Sken break; 3057265236Sken 3058265236Sken lunid = xpt_path_lun_id(path); 3059265236Sken 3060265236Sken SLIST_FOREACH(lun, &target->luns, lun_link) { 3061265236Sken if (lun->lun_id == lunid) { 3062265236Sken found_lun = 1; 3063265236Sken break; 3064265236Sken } 3065265236Sken } 3066265236Sken 3067265236Sken if (found_lun == 0) { 3068265236Sken lun = malloc(sizeof(struct mprsas_lun), M_MPR, 3069265236Sken M_NOWAIT | M_ZERO); 3070265236Sken if (lun == NULL) { 3071265236Sken mpr_dprint(sc, MPR_ERROR, "Unable to alloc " 3072265236Sken "LUN for EEDP support.\n"); 3073265236Sken break; 3074265236Sken } 3075265236Sken lun->lun_id = lunid; 3076265236Sken SLIST_INSERT_HEAD(&target->luns, lun, lun_link); 3077265236Sken } 3078265236Sken 3079265236Sken bzero(&rcap_buf, sizeof(rcap_buf)); 3080265236Sken xpt_setup_ccb(&cdai.ccb_h, path, CAM_PRIORITY_NORMAL); 3081265236Sken cdai.ccb_h.func_code = XPT_DEV_ADVINFO; 3082265236Sken cdai.ccb_h.flags = CAM_DIR_IN; 3083265236Sken cdai.buftype = CDAI_TYPE_RCAPLONG; 3084265236Sken cdai.flags = 0; 3085265236Sken cdai.bufsiz = sizeof(rcap_buf); 3086265236Sken cdai.buf = (uint8_t *)&rcap_buf; 3087265236Sken xpt_action((union ccb *)&cdai); 3088265236Sken if ((cdai.ccb_h.status & CAM_DEV_QFRZN) != 0) 3089265236Sken cam_release_devq(cdai.ccb_h.path, 0, 0, 0, FALSE); 3090265236Sken 3091265236Sken if (((cdai.ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP) 3092265236Sken && (rcap_buf.prot & SRC16_PROT_EN)) { 3093265236Sken lun->eedp_formatted = TRUE; 3094265236Sken lun->eedp_block_size = scsi_4btoul(rcap_buf.length); 3095265236Sken } else { 3096265236Sken lun->eedp_formatted = FALSE; 3097265236Sken lun->eedp_block_size = 0; 3098265236Sken } 3099265236Sken break; 3100265236Sken } 3101265236Sken#endif 3102265236Sken case AC_FOUND_DEVICE: { 3103265236Sken struct ccb_getdev *cgd; 3104265236Sken 3105265729Sken /* 3106265729Sken * See the comment in mpr_attach_sas() for a detailed 3107265729Sken * explanation. In these versions of FreeBSD we register 3108265729Sken * for all events and filter out the events that don't 3109265729Sken * apply to us. 3110265729Sken */ 3111265729Sken#if (__FreeBSD_version < 1000703) || \ 3112265729Sken ((__FreeBSD_version >= 1100000) && (__FreeBSD_version < 1100002)) 3113265729Sken if (xpt_path_path_id(path) != sc->sassc->sim->path_id) 3114265729Sken break; 3115265729Sken#endif 3116265729Sken 3117265236Sken cgd = arg; 3118265236Sken mprsas_prepare_ssu(sc, path, cgd); 3119265729Sken 3120265236Sken#if (__FreeBSD_version < 901503) || \ 3121265236Sken ((__FreeBSD_version >= 1000000) && (__FreeBSD_version < 1000006)) 3122265236Sken mprsas_check_eedp(sc, path, cgd); 3123265236Sken#endif 3124265236Sken break; 3125265236Sken } 3126265236Sken default: 3127265236Sken break; 3128265236Sken } 3129265236Sken} 3130265236Sken 3131265236Skenstatic void 3132265236Skenmprsas_prepare_ssu(struct mpr_softc *sc, struct cam_path *path, 3133265236Sken struct ccb_getdev *cgd) 3134265236Sken{ 3135265236Sken struct mprsas_softc *sassc = sc->sassc; 3136265236Sken path_id_t pathid; 3137265236Sken target_id_t targetid; 3138265236Sken lun_id_t lunid; 3139265236Sken struct mprsas_target *target; 3140265236Sken struct mprsas_lun *lun; 3141265236Sken uint8_t found_lun; 3142265236Sken 3143265236Sken sassc = sc->sassc; 3144265236Sken pathid = cam_sim_path(sassc->sim); 3145265236Sken targetid = xpt_path_target_id(path); 3146265236Sken lunid = xpt_path_lun_id(path); 3147265236Sken 3148265236Sken KASSERT(targetid < sassc->maxtargets, 3149265236Sken ("Target %d out of bounds in mprsas_prepare_ssu\n", targetid)); 3150265236Sken target = &sassc->targets[targetid]; 3151265236Sken if (target->handle == 0x0) 3152265236Sken return; 3153265236Sken 3154265236Sken /* 3155265236Sken * If LUN is already in list, don't create a new one. 3156265236Sken */ 3157265236Sken found_lun = FALSE; 3158265236Sken SLIST_FOREACH(lun, &target->luns, lun_link) { 3159265236Sken if (lun->lun_id == lunid) { 3160265236Sken found_lun = TRUE; 3161265236Sken break; 3162265236Sken } 3163265236Sken } 3164265236Sken if (!found_lun) { 3165265236Sken lun = malloc(sizeof(struct mprsas_lun), M_MPR, 3166265236Sken M_NOWAIT | M_ZERO); 3167265236Sken if (lun == NULL) { 3168265236Sken mpr_dprint(sc, MPR_ERROR, "Unable to alloc LUN for " 3169265236Sken "preparing SSU.\n"); 3170265236Sken return; 3171265236Sken } 3172265236Sken lun->lun_id = lunid; 3173265236Sken SLIST_INSERT_HEAD(&target->luns, lun, lun_link); 3174265236Sken } 3175265236Sken 3176265236Sken /* 3177265236Sken * If this is a SATA direct-access end device, mark it so that a SCSI 3178265236Sken * StartStopUnit command will be sent to it when the driver is being 3179265236Sken * shutdown. 3180265236Sken */ 3181265236Sken if (((cgd->inq_data.device & 0x1F) == T_DIRECT) && 3182265236Sken (target->devinfo & MPI2_SAS_DEVICE_INFO_SATA_DEVICE) && 3183265236Sken ((target->devinfo & MPI2_SAS_DEVICE_INFO_MASK_DEVICE_TYPE) == 3184265236Sken MPI2_SAS_DEVICE_INFO_END_DEVICE)) { 3185265236Sken lun->stop_at_shutdown = TRUE; 3186265236Sken } 3187265236Sken} 3188265236Sken 3189265236Sken#if (__FreeBSD_version < 901503) || \ 3190265236Sken ((__FreeBSD_version >= 1000000) && (__FreeBSD_version < 1000006)) 3191265236Skenstatic void 3192265236Skenmprsas_check_eedp(struct mpr_softc *sc, struct cam_path *path, 3193265236Sken struct ccb_getdev *cgd) 3194265236Sken{ 3195265236Sken struct mprsas_softc *sassc = sc->sassc; 3196265236Sken struct ccb_scsiio *csio; 3197265236Sken struct scsi_read_capacity_16 *scsi_cmd; 3198265236Sken struct scsi_read_capacity_eedp *rcap_buf; 3199265236Sken path_id_t pathid; 3200265236Sken target_id_t targetid; 3201265236Sken lun_id_t lunid; 3202265236Sken union ccb *ccb; 3203265236Sken struct cam_path *local_path; 3204265236Sken struct mprsas_target *target; 3205265236Sken struct mprsas_lun *lun; 3206265236Sken uint8_t found_lun; 3207265236Sken char path_str[64]; 3208265236Sken 3209265236Sken sassc = sc->sassc; 3210265236Sken pathid = cam_sim_path(sassc->sim); 3211265236Sken targetid = xpt_path_target_id(path); 3212265236Sken lunid = xpt_path_lun_id(path); 3213265236Sken 3214265236Sken KASSERT(targetid < sassc->maxtargets, 3215265236Sken ("Target %d out of bounds in mprsas_check_eedp\n", targetid)); 3216265236Sken target = &sassc->targets[targetid]; 3217265236Sken if (target->handle == 0x0) 3218265236Sken return; 3219265236Sken 3220265236Sken /* 3221265236Sken * Determine if the device is EEDP capable. 3222265236Sken * 3223265236Sken * If this flag is set in the inquiry data, the device supports 3224265236Sken * protection information, and must support the 16 byte read capacity 3225265236Sken * command, otherwise continue without sending read cap 16 3226265236Sken */ 3227265236Sken if ((cgd->inq_data.spc3_flags & SPC3_SID_PROTECT) == 0) 3228265236Sken return; 3229265236Sken 3230265236Sken /* 3231265236Sken * Issue a READ CAPACITY 16 command. This info is used to determine if 3232265236Sken * the LUN is formatted for EEDP support. 3233265236Sken */ 3234265236Sken ccb = xpt_alloc_ccb_nowait(); 3235265236Sken if (ccb == NULL) { 3236265236Sken mpr_dprint(sc, MPR_ERROR, "Unable to alloc CCB for EEDP " 3237265236Sken "support.\n"); 3238265236Sken return; 3239265236Sken } 3240265236Sken 3241265236Sken if (xpt_create_path(&local_path, xpt_periph, pathid, targetid, lunid) 3242265236Sken != CAM_REQ_CMP) { 3243265236Sken mpr_dprint(sc, MPR_ERROR, "Unable to create path for EEDP " 3244265236Sken "support\n"); 3245265236Sken xpt_free_ccb(ccb); 3246265236Sken return; 3247265236Sken } 3248265236Sken 3249265236Sken /* 3250265236Sken * If LUN is already in list, don't create a new one. 3251265236Sken */ 3252265236Sken found_lun = FALSE; 3253265236Sken SLIST_FOREACH(lun, &target->luns, lun_link) { 3254265236Sken if (lun->lun_id == lunid) { 3255265236Sken found_lun = TRUE; 3256265236Sken break; 3257265236Sken } 3258265236Sken } 3259265236Sken if (!found_lun) { 3260265236Sken lun = malloc(sizeof(struct mprsas_lun), M_MPR, 3261265236Sken M_NOWAIT | M_ZERO); 3262265236Sken if (lun == NULL) { 3263265236Sken mpr_dprint(sc, MPR_ERROR, "Unable to alloc LUN for " 3264265236Sken "EEDP support.\n"); 3265265236Sken xpt_free_path(local_path); 3266265236Sken xpt_free_ccb(ccb); 3267265236Sken return; 3268265236Sken } 3269265236Sken lun->lun_id = lunid; 3270265236Sken SLIST_INSERT_HEAD(&target->luns, lun, lun_link); 3271265236Sken } 3272265236Sken 3273265236Sken xpt_path_string(local_path, path_str, sizeof(path_str)); 3274265236Sken mpr_dprint(sc, MPR_INFO, "Sending read cap: path %s handle %d\n", 3275265236Sken path_str, target->handle); 3276265236Sken 3277265236Sken /* 3278265236Sken * Issue a READ CAPACITY 16 command for the LUN. The 3279265236Sken * mprsas_read_cap_done function will load the read cap info into the 3280265236Sken * LUN struct. 3281265236Sken */ 3282265236Sken rcap_buf = malloc(sizeof(struct scsi_read_capacity_eedp), M_MPR, 3283265236Sken M_NOWAIT | M_ZERO); 3284265236Sken if (rcap_buf == NULL) { 3285265236Sken mpr_dprint(sc, MPR_FAULT, "Unable to alloc read capacity " 3286265236Sken "buffer for EEDP support.\n"); 3287265236Sken xpt_free_path(ccb->ccb_h.path); 3288265236Sken xpt_free_ccb(ccb); 3289265236Sken return; 3290265236Sken } 3291265236Sken xpt_setup_ccb(&ccb->ccb_h, local_path, CAM_PRIORITY_XPT); 3292265236Sken csio = &ccb->csio; 3293265236Sken csio->ccb_h.func_code = XPT_SCSI_IO; 3294265236Sken csio->ccb_h.flags = CAM_DIR_IN; 3295265236Sken csio->ccb_h.retry_count = 4; 3296265236Sken csio->ccb_h.cbfcnp = mprsas_read_cap_done; 3297265236Sken csio->ccb_h.timeout = 60000; 3298265236Sken csio->data_ptr = (uint8_t *)rcap_buf; 3299265236Sken csio->dxfer_len = sizeof(struct scsi_read_capacity_eedp); 3300265236Sken csio->sense_len = MPR_SENSE_LEN; 3301265236Sken csio->cdb_len = sizeof(*scsi_cmd); 3302265236Sken csio->tag_action = MSG_SIMPLE_Q_TAG; 3303265236Sken 3304265236Sken scsi_cmd = (struct scsi_read_capacity_16 *)&csio->cdb_io.cdb_bytes; 3305265236Sken bzero(scsi_cmd, sizeof(*scsi_cmd)); 3306265236Sken scsi_cmd->opcode = 0x9E; 3307265236Sken scsi_cmd->service_action = SRC16_SERVICE_ACTION; 3308265236Sken ((uint8_t *)scsi_cmd)[13] = sizeof(struct scsi_read_capacity_eedp); 3309265236Sken 3310265236Sken ccb->ccb_h.ppriv_ptr1 = sassc; 3311265236Sken xpt_action(ccb); 3312265236Sken} 3313265236Sken 3314265236Skenstatic void 3315265236Skenmprsas_read_cap_done(struct cam_periph *periph, union ccb *done_ccb) 3316265236Sken{ 3317265236Sken struct mprsas_softc *sassc; 3318265236Sken struct mprsas_target *target; 3319265236Sken struct mprsas_lun *lun; 3320265236Sken struct scsi_read_capacity_eedp *rcap_buf; 3321265236Sken 3322265236Sken if (done_ccb == NULL) 3323265236Sken return; 3324265236Sken 3325265236Sken /* Driver need to release devq, it Scsi command is 3326265236Sken * generated by driver internally. 3327265236Sken * Currently there is a single place where driver 3328265236Sken * calls scsi command internally. In future if driver 3329265236Sken * calls more scsi command internally, it needs to release 3330265236Sken * devq internally, since those command will not go back to 3331265236Sken * cam_periph. 3332265236Sken */ 3333265236Sken if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) ) { 3334265236Sken done_ccb->ccb_h.status &= ~CAM_DEV_QFRZN; 3335265236Sken xpt_release_devq(done_ccb->ccb_h.path, 3336265236Sken /*count*/ 1, /*run_queue*/TRUE); 3337265236Sken } 3338265236Sken 3339265236Sken rcap_buf = (struct scsi_read_capacity_eedp *)done_ccb->csio.data_ptr; 3340265236Sken 3341265236Sken /* 3342265236Sken * Get the LUN ID for the path and look it up in the LUN list for the 3343265236Sken * target. 3344265236Sken */ 3345265236Sken sassc = (struct mprsas_softc *)done_ccb->ccb_h.ppriv_ptr1; 3346265236Sken KASSERT(done_ccb->ccb_h.target_id < sassc->maxtargets, 3347265236Sken ("Target %d out of bounds in mprsas_read_cap_done\n", 3348265236Sken done_ccb->ccb_h.target_id)); 3349265236Sken target = &sassc->targets[done_ccb->ccb_h.target_id]; 3350265236Sken SLIST_FOREACH(lun, &target->luns, lun_link) { 3351265236Sken if (lun->lun_id != done_ccb->ccb_h.target_lun) 3352265236Sken continue; 3353265236Sken 3354265236Sken /* 3355265236Sken * Got the LUN in the target's LUN list. Fill it in with EEDP 3356265236Sken * info. If the READ CAP 16 command had some SCSI error (common 3357265236Sken * if command is not supported), mark the lun as not supporting 3358265236Sken * EEDP and set the block size to 0. 3359265236Sken */ 3360265236Sken if (((done_ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) 3361265236Sken || (done_ccb->csio.scsi_status != SCSI_STATUS_OK)) { 3362265236Sken lun->eedp_formatted = FALSE; 3363265236Sken lun->eedp_block_size = 0; 3364265236Sken break; 3365265236Sken } 3366265236Sken 3367265236Sken if (rcap_buf->protect & 0x01) { 3368265236Sken mpr_dprint(sassc->sc, MPR_INFO, "LUN %d for " 3369265236Sken "target ID %d is formatted for EEDP " 3370265236Sken "support.\n", done_ccb->ccb_h.target_lun, 3371265236Sken done_ccb->ccb_h.target_id); 3372265236Sken lun->eedp_formatted = TRUE; 3373265236Sken lun->eedp_block_size = scsi_4btoul(rcap_buf->length); 3374265236Sken } 3375265236Sken break; 3376265236Sken } 3377265236Sken 3378265236Sken // Finished with this CCB and path. 3379265236Sken free(rcap_buf, M_MPR); 3380265236Sken xpt_free_path(done_ccb->ccb_h.path); 3381265236Sken xpt_free_ccb(done_ccb); 3382265236Sken} 3383265236Sken#endif /* (__FreeBSD_version < 901503) || \ 3384265236Sken ((__FreeBSD_version >= 1000000) && (__FreeBSD_version < 1000006)) */ 3385265236Sken 3386265236Skenint 3387265236Skenmprsas_startup(struct mpr_softc *sc) 3388265236Sken{ 3389265236Sken /* 3390265236Sken * Send the port enable message and set the wait_for_port_enable flag. 3391265236Sken * This flag helps to keep the simq frozen until all discovery events 3392265236Sken * are processed. 3393265236Sken */ 3394265236Sken sc->wait_for_port_enable = 1; 3395265236Sken mprsas_send_portenable(sc); 3396265236Sken return (0); 3397265236Sken} 3398265236Sken 3399265236Skenstatic int 3400265236Skenmprsas_send_portenable(struct mpr_softc *sc) 3401265236Sken{ 3402265236Sken MPI2_PORT_ENABLE_REQUEST *request; 3403265236Sken struct mpr_command *cm; 3404265236Sken 3405265236Sken MPR_FUNCTRACE(sc); 3406265236Sken 3407265236Sken if ((cm = mpr_alloc_command(sc)) == NULL) 3408265236Sken return (EBUSY); 3409265236Sken request = (MPI2_PORT_ENABLE_REQUEST *)cm->cm_req; 3410265236Sken request->Function = MPI2_FUNCTION_PORT_ENABLE; 3411265236Sken request->MsgFlags = 0; 3412265236Sken request->VP_ID = 0; 3413265236Sken cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 3414265236Sken cm->cm_complete = mprsas_portenable_complete; 3415265236Sken cm->cm_data = NULL; 3416265236Sken cm->cm_sge = NULL; 3417265236Sken 3418265236Sken mpr_map_command(sc, cm); 3419265236Sken mpr_dprint(sc, MPR_XINFO, 3420265236Sken "mpr_send_portenable finished cm %p req %p complete %p\n", 3421265236Sken cm, cm->cm_req, cm->cm_complete); 3422265236Sken return (0); 3423265236Sken} 3424265236Sken 3425265236Skenstatic void 3426265236Skenmprsas_portenable_complete(struct mpr_softc *sc, struct mpr_command *cm) 3427265236Sken{ 3428265236Sken MPI2_PORT_ENABLE_REPLY *reply; 3429265236Sken struct mprsas_softc *sassc; 3430265236Sken 3431265236Sken MPR_FUNCTRACE(sc); 3432265236Sken sassc = sc->sassc; 3433265236Sken 3434265236Sken /* 3435265236Sken * Currently there should be no way we can hit this case. It only 3436265236Sken * happens when we have a failure to allocate chain frames, and 3437265236Sken * port enable commands don't have S/G lists. 3438265236Sken */ 3439265236Sken if ((cm->cm_flags & MPR_CM_FLAGS_ERROR_MASK) != 0) { 3440265236Sken mpr_dprint(sc, MPR_ERROR, "%s: cm_flags = %#x for port enable! " 3441265236Sken "This should not happen!\n", __func__, cm->cm_flags); 3442265236Sken } 3443265236Sken 3444265236Sken reply = (MPI2_PORT_ENABLE_REPLY *)cm->cm_reply; 3445265236Sken if (reply == NULL) 3446265236Sken mpr_dprint(sc, MPR_FAULT, "Portenable NULL reply\n"); 3447265236Sken else if (le16toh(reply->IOCStatus & MPI2_IOCSTATUS_MASK) != 3448265236Sken MPI2_IOCSTATUS_SUCCESS) 3449265236Sken mpr_dprint(sc, MPR_FAULT, "Portenable failed\n"); 3450265236Sken 3451265236Sken mpr_free_command(sc, cm); 3452265236Sken if (sc->mpr_ich.ich_arg != NULL) { 3453265236Sken mpr_dprint(sc, MPR_XINFO, "disestablish config intrhook\n"); 3454265236Sken config_intrhook_disestablish(&sc->mpr_ich); 3455265236Sken sc->mpr_ich.ich_arg = NULL; 3456265236Sken } 3457265236Sken 3458265236Sken /* 3459265236Sken * Done waiting for port enable to complete. Decrement the refcount. 3460265236Sken * If refcount is 0, discovery is complete and a rescan of the bus can 3461265236Sken * take place. 3462265236Sken */ 3463265236Sken sc->wait_for_port_enable = 0; 3464265236Sken sc->port_enable_complete = 1; 3465265236Sken wakeup(&sc->port_enable_complete); 3466265236Sken mprsas_startup_decrement(sassc); 3467265236Sken} 3468265236Sken 3469265236Skenint 3470265236Skenmprsas_check_id(struct mprsas_softc *sassc, int id) 3471265236Sken{ 3472265236Sken struct mpr_softc *sc = sassc->sc; 3473265236Sken char *ids; 3474265236Sken char *name; 3475265236Sken 3476265236Sken ids = &sc->exclude_ids[0]; 3477265236Sken while((name = strsep(&ids, ",")) != NULL) { 3478265236Sken if (name[0] == '\0') 3479265236Sken continue; 3480265236Sken if (strtol(name, NULL, 0) == (long)id) 3481265236Sken return (1); 3482265236Sken } 3483265236Sken 3484265236Sken return (0); 3485265236Sken} 3486