1212420Sken/*- 2212420Sken * Copyright (c) 2009 Yahoo! Inc. 3237683Sken * Copyright (c) 2011, 2012 LSI Corp. 4212420Sken * All rights reserved. 5212420Sken * 6212420Sken * Redistribution and use in source and binary forms, with or without 7212420Sken * modification, are permitted provided that the following conditions 8212420Sken * are met: 9212420Sken * 1. Redistributions of source code must retain the above copyright 10212420Sken * notice, this list of conditions and the following disclaimer. 11212420Sken * 2. Redistributions in binary form must reproduce the above copyright 12212420Sken * notice, this list of conditions and the following disclaimer in the 13212420Sken * documentation and/or other materials provided with the distribution. 14212420Sken * 15212420Sken * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16212420Sken * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17212420Sken * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18212420Sken * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19212420Sken * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20212420Sken * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21212420Sken * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22212420Sken * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23212420Sken * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24212420Sken * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25212420Sken * SUCH DAMAGE. 26230592Sken * 27230592Sken * LSI MPT-Fusion Host Adapter FreeBSD 28230592Sken * 29230592Sken * $FreeBSD$ 30230592Sken */ 31212420Sken 32212420Sken#include <sys/cdefs.h> 33212420Sken__FBSDID("$FreeBSD$"); 34212420Sken 35212420Sken/* Communications core for LSI MPT2 */ 36212420Sken 37230592Sken/* TODO Move headers to mpsvar */ 38212420Sken#include <sys/types.h> 39212420Sken#include <sys/param.h> 40212420Sken#include <sys/systm.h> 41212420Sken#include <sys/kernel.h> 42212420Sken#include <sys/selinfo.h> 43212420Sken#include <sys/module.h> 44212420Sken#include <sys/bus.h> 45212420Sken#include <sys/conf.h> 46212420Sken#include <sys/bio.h> 47212420Sken#include <sys/malloc.h> 48212420Sken#include <sys/uio.h> 49212420Sken#include <sys/sysctl.h> 50216088Sken#include <sys/endian.h> 51230592Sken#include <sys/queue.h> 52230592Sken#include <sys/kthread.h> 53230592Sken#include <sys/taskqueue.h> 54230592Sken#include <sys/sbuf.h> 55212420Sken 56212420Sken#include <machine/bus.h> 57212420Sken#include <machine/resource.h> 58212420Sken#include <sys/rman.h> 59212420Sken 60230592Sken#include <machine/stdarg.h> 61230592Sken 62212420Sken#include <cam/cam.h> 63212420Sken#include <cam/cam_ccb.h> 64230592Sken#include <cam/cam_xpt.h> 65212420Sken#include <cam/cam_debug.h> 66212420Sken#include <cam/cam_sim.h> 67212420Sken#include <cam/cam_xpt_sim.h> 68212420Sken#include <cam/cam_xpt_periph.h> 69212420Sken#include <cam/cam_periph.h> 70212420Sken#include <cam/scsi/scsi_all.h> 71212420Sken#include <cam/scsi/scsi_message.h> 72216088Sken#if __FreeBSD_version >= 900026 73216088Sken#include <cam/scsi/smp_all.h> 74216088Sken#endif 75212420Sken 76212420Sken#include <dev/mps/mpi/mpi2_type.h> 77212420Sken#include <dev/mps/mpi/mpi2.h> 78212420Sken#include <dev/mps/mpi/mpi2_ioc.h> 79212420Sken#include <dev/mps/mpi/mpi2_sas.h> 80212420Sken#include <dev/mps/mpi/mpi2_cnfg.h> 81212420Sken#include <dev/mps/mpi/mpi2_init.h> 82230592Sken#include <dev/mps/mpi/mpi2_tool.h> 83230592Sken#include <dev/mps/mps_ioctl.h> 84212420Sken#include <dev/mps/mpsvar.h> 85212420Sken#include <dev/mps/mps_table.h> 86230592Sken#include <dev/mps/mps_sas.h> 87212420Sken 88230592Sken#define MPSSAS_DISCOVERY_TIMEOUT 20 89230592Sken#define MPSSAS_MAX_DISCOVERY_TIMEOUTS 10 /* 200 seconds */ 90212420Sken 91230592Sken/* 92230592Sken * static array to check SCSI OpCode for EEDP protection bits 93230592Sken */ 94230592Sken#define PRO_R MPI2_SCSIIO_EEDPFLAGS_CHECK_REMOVE_OP 95230592Sken#define PRO_W MPI2_SCSIIO_EEDPFLAGS_INSERT_OP 96230592Sken#define PRO_V MPI2_SCSIIO_EEDPFLAGS_INSERT_OP 97230592Skenstatic uint8_t op_code_prot[256] = { 98230592Sken 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 99230592Sken 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 100230592Sken 0, 0, 0, 0, 0, 0, 0, 0, PRO_R, 0, PRO_W, 0, 0, 0, PRO_W, PRO_V, 101230592Sken 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 102230592Sken 0, PRO_W, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 103230592Sken 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 104230592Sken 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 105230592Sken 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 106230592Sken 0, 0, 0, 0, 0, 0, 0, 0, PRO_R, 0, PRO_W, 0, 0, 0, PRO_W, PRO_V, 107230592Sken 0, 0, 0, PRO_W, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 108230592Sken 0, 0, 0, 0, 0, 0, 0, 0, PRO_R, 0, PRO_W, 0, 0, 0, PRO_W, PRO_V, 109230592Sken 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 110230592Sken 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 111230592Sken 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 112230592Sken 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 113230592Sken 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 114212420Sken}; 115212420Sken 116230592SkenMALLOC_DEFINE(M_MPSSAS, "MPSSAS", "MPS SAS memory"); 117212420Sken 118212420Skenstatic void mpssas_discovery_timeout(void *data); 119212420Skenstatic void mpssas_remove_device(struct mps_softc *, struct mps_command *); 120212420Skenstatic void mpssas_remove_complete(struct mps_softc *, struct mps_command *); 121212420Skenstatic void mpssas_action(struct cam_sim *sim, union ccb *ccb); 122212420Skenstatic void mpssas_poll(struct cam_sim *sim); 123212420Skenstatic void mpssas_scsiio_timeout(void *data); 124212420Skenstatic void mpssas_abort_complete(struct mps_softc *sc, struct mps_command *cm); 125230592Skenstatic void mpssas_direct_drive_io(struct mpssas_softc *sassc, 126230592Sken struct mps_command *cm, union ccb *ccb); 127212420Skenstatic void mpssas_action_scsiio(struct mpssas_softc *, union ccb *); 128212420Skenstatic void mpssas_scsiio_complete(struct mps_softc *, struct mps_command *); 129230592Skenstatic void mpssas_action_resetdev(struct mpssas_softc *, union ccb *); 130216088Sken#if __FreeBSD_version >= 900026 131216088Skenstatic void mpssas_smpio_complete(struct mps_softc *sc, struct mps_command *cm); 132216088Skenstatic void mpssas_send_smpcmd(struct mpssas_softc *sassc, union ccb *ccb, 133216088Sken uint64_t sasaddr); 134216088Skenstatic void mpssas_action_smpio(struct mpssas_softc *sassc, union ccb *ccb); 135230592Sken#endif //FreeBSD_version >= 900026 136212420Skenstatic void mpssas_resetdev_complete(struct mps_softc *, struct mps_command *); 137230592Skenstatic int mpssas_send_abort(struct mps_softc *sc, struct mps_command *tm, struct mps_command *cm); 138230592Skenstatic int mpssas_send_reset(struct mps_softc *sc, struct mps_command *tm, uint8_t type); 139230592Skenstatic void mpssas_async(void *callback_arg, uint32_t code, 140230592Sken struct cam_path *path, void *arg); 141253549Sken#if (__FreeBSD_version < 901503) || \ 142253549Sken ((__FreeBSD_version >= 1000000) && (__FreeBSD_version < 1000006)) 143253549Skenstatic void mpssas_check_eedp(struct mps_softc *sc, struct cam_path *path, 144253549Sken struct ccb_getdev *cgd); 145230592Skenstatic void mpssas_read_cap_done(struct cam_periph *periph, union ccb *done_ccb); 146230592Sken#endif 147230592Skenstatic int mpssas_send_portenable(struct mps_softc *sc); 148230592Skenstatic void mpssas_portenable_complete(struct mps_softc *sc, 149230592Sken struct mps_command *cm); 150212420Sken 151231240Skenstruct mpssas_target * 152230592Skenmpssas_find_target_by_handle(struct mpssas_softc *sassc, int start, uint16_t handle) 153216368Sken{ 154230592Sken struct mpssas_target *target; 155230592Sken int i; 156216368Sken 157230592Sken for (i = start; i < sassc->sc->facts->MaxTargets; i++) { 158230592Sken target = &sassc->targets[i]; 159230592Sken if (target->handle == handle) 160230592Sken return (target); 161216368Sken } 162216368Sken 163230592Sken return (NULL); 164216368Sken} 165216368Sken 166230592Sken/* we need to freeze the simq during attach and diag reset, to avoid failing 167230592Sken * commands before device handles have been found by discovery. Since 168230592Sken * discovery involves reading config pages and possibly sending commands, 169230592Sken * discovery actions may continue even after we receive the end of discovery 170230592Sken * event, so refcount discovery actions instead of assuming we can unfreeze 171230592Sken * the simq when we get the event. 172230592Sken */ 173230592Skenvoid 174230592Skenmpssas_startup_increment(struct mpssas_softc *sassc) 175212420Sken{ 176253460Sscottl MPS_FUNCTRACE(sassc->sc); 177253460Sscottl 178230592Sken if ((sassc->flags & MPSSAS_IN_STARTUP) != 0) { 179230592Sken if (sassc->startup_refcount++ == 0) { 180230592Sken /* just starting, freeze the simq */ 181253460Sscottl mps_dprint(sassc->sc, MPS_INIT, 182230592Sken "%s freezing simq\n", __func__); 183230592Sken xpt_freeze_simq(sassc->sim, 1); 184230592Sken } 185253460Sscottl mps_dprint(sassc->sc, MPS_INIT, "%s refcount %u\n", __func__, 186230592Sken sassc->startup_refcount); 187230592Sken } 188230592Sken} 189212420Sken 190230592Skenvoid 191230592Skenmpssas_startup_decrement(struct mpssas_softc *sassc) 192230592Sken{ 193253460Sscottl MPS_FUNCTRACE(sassc->sc); 194253460Sscottl 195230592Sken if ((sassc->flags & MPSSAS_IN_STARTUP) != 0) { 196230592Sken if (--sassc->startup_refcount == 0) { 197230592Sken /* finished all discovery-related actions, release 198230592Sken * the simq and rescan for the latest topology. 199230592Sken */ 200253460Sscottl mps_dprint(sassc->sc, MPS_INIT, 201230592Sken "%s releasing simq\n", __func__); 202230592Sken sassc->flags &= ~MPSSAS_IN_STARTUP; 203253549Sken#if __FreeBSD_version >= 1000039 204253549Sken xpt_release_boot(); 205253549Sken#else 206230592Sken xpt_release_simq(sassc->sim, 1); 207230592Sken mpssas_rescan_target(sassc->sc, NULL); 208253549Sken#endif 209230592Sken } 210253460Sscottl mps_dprint(sassc->sc, MPS_INIT, "%s refcount %u\n", __func__, 211230592Sken sassc->startup_refcount); 212212420Sken } 213230592Sken} 214212420Sken 215230592Sken/* LSI's firmware requires us to stop sending commands when we're doing task 216230592Sken * management, so refcount the TMs and keep the simq frozen when any are in 217230592Sken * use. 218230592Sken */ 219230592Skenstruct mps_command * 220230592Skenmpssas_alloc_tm(struct mps_softc *sc) 221230592Sken{ 222230592Sken struct mps_command *tm; 223212420Sken 224253460Sscottl MPS_FUNCTRACE(sc); 225230592Sken tm = mps_alloc_high_priority_command(sc); 226230592Sken if (tm != NULL) { 227230592Sken if (sc->sassc->tm_count++ == 0) { 228253460Sscottl mps_dprint(sc, MPS_RECOVERY, 229253460Sscottl "%s freezing simq\n", __func__); 230230592Sken xpt_freeze_simq(sc->sassc->sim, 1); 231230592Sken } 232253460Sscottl mps_dprint(sc, MPS_RECOVERY, "%s tm_count %u\n", __func__, 233230592Sken sc->sassc->tm_count); 234230592Sken } 235230592Sken return tm; 236212420Sken} 237212420Sken 238230592Skenvoid 239230592Skenmpssas_free_tm(struct mps_softc *sc, struct mps_command *tm) 240212420Sken{ 241253460Sscottl mps_dprint(sc, MPS_TRACE, "%s", __func__); 242230592Sken if (tm == NULL) 243230592Sken return; 244212420Sken 245230592Sken /* if there are no TMs in use, we can release the simq. We use our 246230592Sken * own refcount so that it's easier for a diag reset to cleanup and 247230592Sken * release the simq. 248230592Sken */ 249230592Sken if (--sc->sassc->tm_count == 0) { 250253460Sscottl mps_dprint(sc, MPS_RECOVERY, "%s releasing simq\n", __func__); 251230592Sken xpt_release_simq(sc->sassc->sim, 1); 252212420Sken } 253253460Sscottl mps_dprint(sc, MPS_RECOVERY, "%s tm_count %u\n", __func__, 254230592Sken sc->sassc->tm_count); 255212420Sken 256230592Sken mps_free_high_priority_command(sc, tm); 257212420Sken} 258212420Sken 259230592Skenvoid 260230592Skenmpssas_rescan_target(struct mps_softc *sc, struct mpssas_target *targ) 261212420Sken{ 262230592Sken struct mpssas_softc *sassc = sc->sassc; 263230592Sken path_id_t pathid; 264230592Sken target_id_t targetid; 265230592Sken union ccb *ccb; 266212420Sken 267253460Sscottl MPS_FUNCTRACE(sc); 268230592Sken pathid = cam_sim_path(sassc->sim); 269230592Sken if (targ == NULL) 270230592Sken targetid = CAM_TARGET_WILDCARD; 271230592Sken else 272230592Sken targetid = targ - sassc->targets; 273212420Sken 274230592Sken /* 275230592Sken * Allocate a CCB and schedule a rescan. 276230592Sken */ 277230592Sken ccb = xpt_alloc_ccb_nowait(); 278230592Sken if (ccb == NULL) { 279253460Sscottl mps_dprint(sc, MPS_ERROR, "unable to alloc CCB for rescan\n"); 280212420Sken return; 281212420Sken } 282212420Sken 283249468Smav if (xpt_create_path(&ccb->ccb_h.path, NULL, pathid, 284253550Sken targetid, CAM_LUN_WILDCARD) != CAM_REQ_CMP) { 285253460Sscottl mps_dprint(sc, MPS_ERROR, "unable to create path for rescan\n"); 286230592Sken xpt_free_ccb(ccb); 287212420Sken return; 288212420Sken } 289230592Sken 290237800Sken if (targetid == CAM_TARGET_WILDCARD) 291237800Sken ccb->ccb_h.func_code = XPT_SCAN_BUS; 292237800Sken else 293237800Sken ccb->ccb_h.func_code = XPT_SCAN_TGT; 294237800Sken 295230592Sken mps_dprint(sc, MPS_TRACE, "%s targetid %u\n", __func__, targetid); 296253549Sken xpt_rescan(ccb); 297212420Sken} 298212420Sken 299212420Skenstatic void 300253460Sscottlmpssas_log_command(struct mps_command *cm, u_int level, const char *fmt, ...) 301212420Sken{ 302230592Sken struct sbuf sb; 303230592Sken va_list ap; 304230592Sken char str[192]; 305230592Sken char path_str[64]; 306212420Sken 307230592Sken if (cm == NULL) 308230592Sken return; 309212420Sken 310254253Sscottl /* No need to be in here if debugging isn't enabled */ 311254257Smav if ((cm->cm_sc->mps_debug & level) == 0) 312254253Sscottl return; 313254253Sscottl 314230592Sken sbuf_new(&sb, str, sizeof(str), 0); 315212420Sken 316230592Sken va_start(ap, fmt); 317212420Sken 318230592Sken if (cm->cm_ccb != NULL) { 319230592Sken xpt_path_string(cm->cm_ccb->csio.ccb_h.path, path_str, 320230592Sken sizeof(path_str)); 321230592Sken sbuf_cat(&sb, path_str); 322230592Sken if (cm->cm_ccb->ccb_h.func_code == XPT_SCSI_IO) { 323230592Sken scsi_command_string(&cm->cm_ccb->csio, &sb); 324230592Sken sbuf_printf(&sb, "length %d ", 325230592Sken cm->cm_ccb->csio.dxfer_len); 326212420Sken } 327212420Sken } 328230592Sken else { 329230592Sken sbuf_printf(&sb, "(noperiph:%s%d:%u:%u:%u): ", 330230592Sken cam_sim_name(cm->cm_sc->sassc->sim), 331230592Sken cam_sim_unit(cm->cm_sc->sassc->sim), 332230592Sken cam_sim_bus(cm->cm_sc->sassc->sim), 333230592Sken cm->cm_targ ? cm->cm_targ->tid : 0xFFFFFFFF, 334230592Sken cm->cm_lun); 335230592Sken } 336212420Sken 337230592Sken sbuf_printf(&sb, "SMID %u ", cm->cm_desc.Default.SMID); 338230592Sken sbuf_vprintf(&sb, fmt, ap); 339230592Sken sbuf_finish(&sb); 340253460Sscottl mps_dprint_field(cm->cm_sc, level, "%s", sbuf_data(&sb)); 341212420Sken 342230592Sken va_end(ap); 343230592Sken} 344212420Sken 345231240Sken 346230592Skenstatic void 347231240Skenmpssas_remove_volume(struct mps_softc *sc, struct mps_command *tm) 348230592Sken{ 349231240Sken MPI2_SCSI_TASK_MANAGE_REPLY *reply; 350231240Sken struct mpssas_target *targ; 351231240Sken uint16_t handle; 352212420Sken 353253460Sscottl MPS_FUNCTRACE(sc); 354231240Sken 355231240Sken reply = (MPI2_SCSI_TASK_MANAGE_REPLY *)tm->cm_reply; 356231240Sken handle = (uint16_t)(uintptr_t)tm->cm_complete_data; 357231240Sken targ = tm->cm_targ; 358231240Sken 359231240Sken if (reply == NULL) { 360231240Sken /* XXX retry the remove after the diag reset completes? */ 361253460Sscottl mps_dprint(sc, MPS_FAULT, 362253460Sscottl "%s NULL reply reseting device 0x%04x\n", __func__, handle); 363231240Sken mpssas_free_tm(sc, tm); 364230592Sken return; 365230592Sken } 366212420Sken 367231240Sken if (reply->IOCStatus != MPI2_IOCSTATUS_SUCCESS) { 368253460Sscottl mps_dprint(sc, MPS_FAULT, 369253460Sscottl "IOCStatus = 0x%x while resetting device 0x%x\n", 370231240Sken reply->IOCStatus, handle); 371231240Sken mpssas_free_tm(sc, tm); 372231240Sken return; 373231240Sken } 374231240Sken 375253460Sscottl mps_dprint(sc, MPS_XINFO, 376253460Sscottl "Reset aborted %u commands\n", reply->TerminationCount); 377231240Sken mps_free_reply(sc, tm->cm_reply_data); 378240518Seadler tm->cm_reply = NULL; /* Ensures the reply won't get re-freed */ 379231240Sken 380253460Sscottl mps_dprint(sc, MPS_XINFO, 381253460Sscottl "clearing target %u handle 0x%04x\n", targ->tid, handle); 382231240Sken 383231240Sken /* 384231240Sken * Don't clear target if remove fails because things will get confusing. 385231240Sken * Leave the devname and sasaddr intact so that we know to avoid reusing 386231240Sken * this target id if possible, and so we can assign the same target id 387231240Sken * to this device if it comes back in the future. 388231240Sken */ 389231240Sken if (reply->IOCStatus == MPI2_IOCSTATUS_SUCCESS) { 390231240Sken targ = tm->cm_targ; 391231240Sken targ->handle = 0x0; 392231240Sken targ->encl_handle = 0x0; 393231240Sken targ->encl_slot = 0x0; 394231240Sken targ->exp_dev_handle = 0x0; 395231240Sken targ->phy_num = 0x0; 396231240Sken targ->linkrate = 0x0; 397231240Sken targ->devinfo = 0x0; 398231240Sken targ->flags = 0x0; 399231240Sken } 400231240Sken 401231240Sken mpssas_free_tm(sc, tm); 402212420Sken} 403212420Sken 404231240Sken 405212420Sken/* 406231240Sken * No Need to call "MPI2_SAS_OP_REMOVE_DEVICE" For Volume removal. 407231240Sken * Otherwise Volume Delete is same as Bare Drive Removal. 408231240Sken */ 409231240Skenvoid 410231240Skenmpssas_prepare_volume_remove(struct mpssas_softc *sassc, uint16_t handle) 411231240Sken{ 412231240Sken MPI2_SCSI_TASK_MANAGE_REQUEST *req; 413231240Sken struct mps_softc *sc; 414231240Sken struct mps_command *cm; 415231240Sken struct mpssas_target *targ = NULL; 416231240Sken 417253460Sscottl MPS_FUNCTRACE(sassc->sc); 418231240Sken sc = sassc->sc; 419231240Sken 420231240Sken#ifdef WD_SUPPORT 421231240Sken /* 422231240Sken * If this is a WD controller, determine if the disk should be exposed 423231240Sken * to the OS or not. If disk should be exposed, return from this 424231240Sken * function without doing anything. 425231240Sken */ 426231240Sken if (sc->WD_available && (sc->WD_hide_expose == 427231240Sken MPS_WD_EXPOSE_ALWAYS)) { 428231240Sken return; 429231240Sken } 430231240Sken#endif //WD_SUPPORT 431231240Sken 432231240Sken targ = mpssas_find_target_by_handle(sassc, 0, handle); 433231240Sken if (targ == NULL) { 434231240Sken /* FIXME: what is the action? */ 435231240Sken /* We don't know about this device? */ 436253460Sscottl mps_dprint(sc, MPS_ERROR, 437253460Sscottl "%s %d : invalid handle 0x%x \n", __func__,__LINE__, handle); 438231240Sken return; 439231240Sken } 440231240Sken 441231240Sken targ->flags |= MPSSAS_TARGET_INREMOVAL; 442231240Sken 443231240Sken cm = mpssas_alloc_tm(sc); 444231240Sken if (cm == NULL) { 445253460Sscottl mps_dprint(sc, MPS_ERROR, 446253460Sscottl "%s: command alloc failure\n", __func__); 447231240Sken return; 448231240Sken } 449231240Sken 450231240Sken mpssas_rescan_target(sc, targ); 451231240Sken 452231240Sken req = (MPI2_SCSI_TASK_MANAGE_REQUEST *)cm->cm_req; 453231240Sken req->DevHandle = targ->handle; 454231240Sken req->Function = MPI2_FUNCTION_SCSI_TASK_MGMT; 455231240Sken req->TaskType = MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET; 456231240Sken 457231240Sken /* SAS Hard Link Reset / SATA Link Reset */ 458231240Sken req->MsgFlags = MPI2_SCSITASKMGMT_MSGFLAGS_LINK_RESET; 459231240Sken 460231240Sken cm->cm_targ = targ; 461231240Sken cm->cm_data = NULL; 462231240Sken cm->cm_desc.HighPriority.RequestFlags = 463231240Sken MPI2_REQ_DESCRIPT_FLAGS_HIGH_PRIORITY; 464231240Sken cm->cm_complete = mpssas_remove_volume; 465231240Sken cm->cm_complete_data = (void *)(uintptr_t)handle; 466231240Sken mps_map_command(sc, cm); 467231240Sken} 468231240Sken 469231240Sken/* 470230592Sken * The MPT2 firmware performs debounce on the link to avoid transient link 471230592Sken * errors and false removals. When it does decide that link has been lost 472230592Sken * and a device need to go away, it expects that the host will perform a 473230592Sken * target reset and then an op remove. The reset has the side-effect of 474230592Sken * aborting any outstanding requests for the device, which is required for 475230592Sken * the op-remove to succeed. It's not clear if the host should check for 476230592Sken * the device coming back alive after the reset. 477212420Sken */ 478230592Skenvoid 479230592Skenmpssas_prepare_remove(struct mpssas_softc *sassc, uint16_t handle) 480212420Sken{ 481212420Sken MPI2_SCSI_TASK_MANAGE_REQUEST *req; 482212420Sken struct mps_softc *sc; 483212420Sken struct mps_command *cm; 484212420Sken struct mpssas_target *targ = NULL; 485212420Sken 486253460Sscottl MPS_FUNCTRACE(sassc->sc); 487212420Sken 488230592Sken sc = sassc->sc; 489230592Sken 490230592Sken targ = mpssas_find_target_by_handle(sassc, 0, handle); 491230592Sken if (targ == NULL) { 492230592Sken /* FIXME: what is the action? */ 493212420Sken /* We don't know about this device? */ 494253460Sscottl mps_dprint(sc, MPS_ERROR, 495253460Sscottl "%s : invalid handle 0x%x \n", __func__, handle); 496212420Sken return; 497230592Sken } 498212420Sken 499230592Sken targ->flags |= MPSSAS_TARGET_INREMOVAL; 500230592Sken 501230592Sken cm = mpssas_alloc_tm(sc); 502212420Sken if (cm == NULL) { 503253460Sscottl mps_dprint(sc, MPS_ERROR, 504253460Sscottl "%s: command alloc failure\n", __func__); 505212420Sken return; 506212420Sken } 507212420Sken 508231240Sken mpssas_rescan_target(sc, targ); 509218811Sken 510212420Sken req = (MPI2_SCSI_TASK_MANAGE_REQUEST *)cm->cm_req; 511218811Sken memset(req, 0, sizeof(*req)); 512237683Sken req->DevHandle = htole16(targ->handle); 513212420Sken req->Function = MPI2_FUNCTION_SCSI_TASK_MGMT; 514212420Sken req->TaskType = MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET; 515212420Sken 516212420Sken /* SAS Hard Link Reset / SATA Link Reset */ 517212420Sken req->MsgFlags = MPI2_SCSITASKMGMT_MSGFLAGS_LINK_RESET; 518212420Sken 519230592Sken cm->cm_targ = targ; 520212420Sken cm->cm_data = NULL; 521230592Sken cm->cm_desc.HighPriority.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_HIGH_PRIORITY; 522212420Sken cm->cm_complete = mpssas_remove_device; 523230592Sken cm->cm_complete_data = (void *)(uintptr_t)handle; 524230592Sken mps_map_command(sc, cm); 525212420Sken} 526212420Sken 527212420Skenstatic void 528230592Skenmpssas_remove_device(struct mps_softc *sc, struct mps_command *tm) 529212420Sken{ 530212420Sken MPI2_SCSI_TASK_MANAGE_REPLY *reply; 531212420Sken MPI2_SAS_IOUNIT_CONTROL_REQUEST *req; 532212420Sken struct mpssas_target *targ; 533218811Sken struct mps_command *next_cm; 534212420Sken uint16_t handle; 535212420Sken 536253460Sscottl MPS_FUNCTRACE(sc); 537212420Sken 538230592Sken reply = (MPI2_SCSI_TASK_MANAGE_REPLY *)tm->cm_reply; 539230592Sken handle = (uint16_t)(uintptr_t)tm->cm_complete_data; 540230592Sken targ = tm->cm_targ; 541213535Sken 542218812Sken /* 543218812Sken * Currently there should be no way we can hit this case. It only 544218812Sken * happens when we have a failure to allocate chain frames, and 545218812Sken * task management commands don't have S/G lists. 546218812Sken */ 547230592Sken if ((tm->cm_flags & MPS_CM_FLAGS_ERROR_MASK) != 0) { 548253460Sscottl mps_dprint(sc, MPS_ERROR, 549253460Sscottl "%s: cm_flags = %#x for remove of handle %#04x! " 550253460Sscottl "This should not happen!\n", __func__, tm->cm_flags, 551253460Sscottl handle); 552230592Sken mpssas_free_tm(sc, tm); 553218812Sken return; 554218812Sken } 555218812Sken 556230592Sken if (reply == NULL) { 557230592Sken /* XXX retry the remove after the diag reset completes? */ 558253460Sscottl mps_dprint(sc, MPS_FAULT, 559253460Sscottl "%s NULL reply reseting device 0x%04x\n", __func__, handle); 560230592Sken mpssas_free_tm(sc, tm); 561230592Sken return; 562230592Sken } 563230592Sken 564237683Sken if (le16toh(reply->IOCStatus) != MPI2_IOCSTATUS_SUCCESS) { 565253460Sscottl mps_dprint(sc, MPS_FAULT, 566253460Sscottl "IOCStatus = 0x%x while resetting device 0x%x\n", 567237683Sken le16toh(reply->IOCStatus), handle); 568230592Sken mpssas_free_tm(sc, tm); 569212420Sken return; 570212420Sken } 571212420Sken 572253460Sscottl mps_dprint(sc, MPS_XINFO, "Reset aborted %u commands\n", 573237683Sken le32toh(reply->TerminationCount)); 574230592Sken mps_free_reply(sc, tm->cm_reply_data); 575240518Seadler tm->cm_reply = NULL; /* Ensures the reply won't get re-freed */ 576212420Sken 577212420Sken /* Reuse the existing command */ 578230592Sken req = (MPI2_SAS_IOUNIT_CONTROL_REQUEST *)tm->cm_req; 579218811Sken memset(req, 0, sizeof(*req)); 580212420Sken req->Function = MPI2_FUNCTION_SAS_IO_UNIT_CONTROL; 581212420Sken req->Operation = MPI2_SAS_OP_REMOVE_DEVICE; 582237683Sken req->DevHandle = htole16(handle); 583230592Sken tm->cm_data = NULL; 584230592Sken tm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 585230592Sken tm->cm_complete = mpssas_remove_complete; 586230592Sken tm->cm_complete_data = (void *)(uintptr_t)handle; 587212420Sken 588230592Sken mps_map_command(sc, tm); 589212420Sken 590253460Sscottl mps_dprint(sc, MPS_XINFO, "clearing target %u handle 0x%04x\n", 591230592Sken targ->tid, handle); 592230592Sken TAILQ_FOREACH_SAFE(tm, &targ->commands, cm_link, next_cm) { 593218811Sken union ccb *ccb; 594218811Sken 595253460Sscottl mps_dprint(sc, MPS_XINFO, "Completing missed command %p\n", tm); 596230592Sken ccb = tm->cm_complete_data; 597218811Sken ccb->ccb_h.status = CAM_DEV_NOT_THERE; 598230592Sken mpssas_scsiio_complete(sc, tm); 599218811Sken } 600212420Sken} 601212420Sken 602212420Skenstatic void 603230592Skenmpssas_remove_complete(struct mps_softc *sc, struct mps_command *tm) 604212420Sken{ 605212420Sken MPI2_SAS_IOUNIT_CONTROL_REPLY *reply; 606230592Sken uint16_t handle; 607230592Sken struct mpssas_target *targ; 608237683Sken struct mpssas_lun *lun; 609212420Sken 610253460Sscottl MPS_FUNCTRACE(sc); 611212420Sken 612230592Sken reply = (MPI2_SAS_IOUNIT_CONTROL_REPLY *)tm->cm_reply; 613230592Sken handle = (uint16_t)(uintptr_t)tm->cm_complete_data; 614212420Sken 615230592Sken /* 616230592Sken * Currently there should be no way we can hit this case. It only 617230592Sken * happens when we have a failure to allocate chain frames, and 618230592Sken * task management commands don't have S/G lists. 619230592Sken */ 620230592Sken if ((tm->cm_flags & MPS_CM_FLAGS_ERROR_MASK) != 0) { 621253460Sscottl mps_dprint(sc, MPS_XINFO, 622253460Sscottl "%s: cm_flags = %#x for remove of handle %#04x! " 623230592Sken "This should not happen!\n", __func__, tm->cm_flags, 624230592Sken handle); 625230592Sken mpssas_free_tm(sc, tm); 626230592Sken return; 627230592Sken } 628212420Sken 629230592Sken if (reply == NULL) { 630230592Sken /* most likely a chip reset */ 631253460Sscottl mps_dprint(sc, MPS_FAULT, 632253460Sscottl "%s NULL reply removing device 0x%04x\n", __func__, handle); 633230592Sken mpssas_free_tm(sc, tm); 634230592Sken return; 635212420Sken } 636212420Sken 637253460Sscottl mps_dprint(sc, MPS_XINFO, 638253460Sscottl "%s on handle 0x%04x, IOCStatus= 0x%x\n", __func__, 639237683Sken handle, le16toh(reply->IOCStatus)); 640212420Sken 641230592Sken /* 642230592Sken * Don't clear target if remove fails because things will get confusing. 643230592Sken * Leave the devname and sasaddr intact so that we know to avoid reusing 644230592Sken * this target id if possible, and so we can assign the same target id 645230592Sken * to this device if it comes back in the future. 646230592Sken */ 647237683Sken if (le16toh(reply->IOCStatus) == MPI2_IOCSTATUS_SUCCESS) { 648230592Sken targ = tm->cm_targ; 649230592Sken targ->handle = 0x0; 650230592Sken targ->encl_handle = 0x0; 651230592Sken targ->encl_slot = 0x0; 652230592Sken targ->exp_dev_handle = 0x0; 653230592Sken targ->phy_num = 0x0; 654230592Sken targ->linkrate = 0x0; 655230592Sken targ->devinfo = 0x0; 656231240Sken targ->flags = 0x0; 657237683Sken 658237683Sken while(!SLIST_EMPTY(&targ->luns)) { 659237683Sken lun = SLIST_FIRST(&targ->luns); 660237683Sken SLIST_REMOVE_HEAD(&targ->luns, lun_link); 661237683Sken free(lun, M_MPT2); 662237683Sken } 663212420Sken } 664237683Sken 665212420Sken 666230592Sken mpssas_free_tm(sc, tm); 667212420Sken} 668212420Sken 669212420Skenstatic int 670212420Skenmpssas_register_events(struct mps_softc *sc) 671212420Sken{ 672237683Sken u32 events[MPI2_EVENT_NOTIFY_EVENTMASK_WORDS]; 673212420Sken 674212420Sken bzero(events, 16); 675212420Sken setbit(events, MPI2_EVENT_SAS_DEVICE_STATUS_CHANGE); 676212420Sken setbit(events, MPI2_EVENT_SAS_DISCOVERY); 677212420Sken setbit(events, MPI2_EVENT_SAS_BROADCAST_PRIMITIVE); 678212420Sken setbit(events, MPI2_EVENT_SAS_INIT_DEVICE_STATUS_CHANGE); 679212420Sken setbit(events, MPI2_EVENT_SAS_INIT_TABLE_OVERFLOW); 680212420Sken setbit(events, MPI2_EVENT_SAS_TOPOLOGY_CHANGE_LIST); 681212420Sken setbit(events, MPI2_EVENT_SAS_ENCL_DEVICE_STATUS_CHANGE); 682230592Sken setbit(events, MPI2_EVENT_IR_CONFIGURATION_CHANGE_LIST); 683230592Sken setbit(events, MPI2_EVENT_IR_VOLUME); 684230592Sken setbit(events, MPI2_EVENT_IR_PHYSICAL_DISK); 685230592Sken setbit(events, MPI2_EVENT_IR_OPERATION_STATUS); 686230592Sken setbit(events, MPI2_EVENT_LOG_ENTRY_ADDED); 687212420Sken 688212420Sken mps_register_events(sc, events, mpssas_evt_handler, NULL, 689212420Sken &sc->sassc->mpssas_eh); 690212420Sken 691212420Sken return (0); 692212420Sken} 693212420Sken 694212420Skenint 695212420Skenmps_attach_sas(struct mps_softc *sc) 696212420Sken{ 697212420Sken struct mpssas_softc *sassc; 698230592Sken cam_status status; 699230592Sken int unit, error = 0; 700212420Sken 701253460Sscottl MPS_FUNCTRACE(sc); 702212420Sken 703212420Sken sassc = malloc(sizeof(struct mpssas_softc), M_MPT2, M_WAITOK|M_ZERO); 704237683Sken if(!sassc) { 705237683Sken device_printf(sc->mps_dev, "Cannot allocate memory %s %d\n", 706237683Sken __func__, __LINE__); 707237683Sken return (ENOMEM); 708237683Sken } 709212420Sken sassc->targets = malloc(sizeof(struct mpssas_target) * 710212420Sken sc->facts->MaxTargets, M_MPT2, M_WAITOK|M_ZERO); 711237683Sken if(!sassc->targets) { 712237683Sken device_printf(sc->mps_dev, "Cannot allocate memory %s %d\n", 713237683Sken __func__, __LINE__); 714237683Sken free(sassc, M_MPT2); 715237683Sken return (ENOMEM); 716237683Sken } 717212420Sken sc->sassc = sassc; 718212420Sken sassc->sc = sc; 719212420Sken 720230592Sken if ((sassc->devq = cam_simq_alloc(sc->num_reqs)) == NULL) { 721253460Sscottl mps_dprint(sc, MPS_ERROR, "Cannot allocate SIMQ\n"); 722212420Sken error = ENOMEM; 723212420Sken goto out; 724212420Sken } 725212420Sken 726230592Sken unit = device_get_unit(sc->mps_dev); 727212420Sken sassc->sim = cam_sim_alloc(mpssas_action, mpssas_poll, "mps", sassc, 728230592Sken unit, &sc->mps_mtx, sc->num_reqs, sc->num_reqs, sassc->devq); 729212420Sken if (sassc->sim == NULL) { 730253460Sscottl mps_dprint(sc, MPS_ERROR, "Cannot allocate SIM\n"); 731212420Sken error = EINVAL; 732212420Sken goto out; 733212420Sken } 734212420Sken 735230592Sken TAILQ_INIT(&sassc->ev_queue); 736230592Sken 737230592Sken /* Initialize taskqueue for Event Handling */ 738230592Sken TASK_INIT(&sassc->ev_task, 0, mpssas_firmware_event_work, sc); 739230592Sken sassc->ev_tq = taskqueue_create("mps_taskq", M_NOWAIT | M_ZERO, 740230592Sken taskqueue_thread_enqueue, &sassc->ev_tq); 741230592Sken 742230592Sken /* Run the task queue with lowest priority */ 743230592Sken taskqueue_start_threads(&sassc->ev_tq, 1, 255, "%s taskq", 744230592Sken device_get_nameunit(sc->mps_dev)); 745230592Sken 746230592Sken mps_lock(sc); 747230592Sken 748212420Sken /* 749212420Sken * XXX There should be a bus for every port on the adapter, but since 750212420Sken * we're just going to fake the topology for now, we'll pretend that 751212420Sken * everything is just a target on a single bus. 752212420Sken */ 753212420Sken if ((error = xpt_bus_register(sassc->sim, sc->mps_dev, 0)) != 0) { 754253460Sscottl mps_dprint(sc, MPS_ERROR, "Error %d registering SCSI bus\n", 755212420Sken error); 756212420Sken mps_unlock(sc); 757212420Sken goto out; 758212420Sken } 759212420Sken 760212420Sken /* 761253549Sken * Assume that discovery events will start right away. 762253549Sken * 763253549Sken * Hold off boot until discovery is complete. 764212420Sken */ 765230592Sken sassc->flags |= MPSSAS_IN_STARTUP | MPSSAS_IN_DISCOVERY; 766253549Sken#if __FreeBSD_version >= 1000039 767253549Sken xpt_hold_boot(); 768253549Sken#else 769212420Sken xpt_freeze_simq(sassc->sim, 1); 770253549Sken#endif 771230592Sken sc->sassc->startup_refcount = 0; 772212420Sken 773212420Sken callout_init(&sassc->discovery_callout, 1 /*mpsafe*/); 774212420Sken sassc->discovery_timeouts = 0; 775212420Sken 776230592Sken sassc->tm_count = 0; 777230592Sken 778253549Sken /* 779253549Sken * Register for async events so we can determine the EEDP 780253549Sken * capabilities of devices. 781253549Sken */ 782253549Sken status = xpt_create_path(&sassc->path, /*periph*/NULL, 783253549Sken cam_sim_path(sc->sassc->sim), CAM_TARGET_WILDCARD, 784253549Sken CAM_LUN_WILDCARD); 785230592Sken if (status != CAM_REQ_CMP) { 786253549Sken mps_printf(sc, "Error %#x creating sim path\n", status); 787253549Sken sassc->path = NULL; 788253549Sken } else { 789253549Sken int event; 790253549Sken 791253549Sken#if (__FreeBSD_version >= 1000006) || \ 792253549Sken ((__FreeBSD_version >= 901503) && (__FreeBSD_version < 1000000)) 793253549Sken event = AC_ADVINFO_CHANGED; 794253549Sken#else 795253549Sken event = AC_FOUND_DEVICE; 796253549Sken#endif 797253549Sken status = xpt_register_async(event, mpssas_async, sc, 798253549Sken sassc->path); 799253549Sken if (status != CAM_REQ_CMP) { 800253549Sken mps_dprint(sc, MPS_ERROR, 801253549Sken "Error %#x registering async handler for " 802253549Sken "AC_ADVINFO_CHANGED events\n", status); 803253549Sken xpt_free_path(sassc->path); 804253549Sken sassc->path = NULL; 805253549Sken } 806230592Sken } 807253549Sken if (status != CAM_REQ_CMP) { 808253549Sken /* 809253549Sken * EEDP use is the exception, not the rule. 810253549Sken * Warn the user, but do not fail to attach. 811253549Sken */ 812253549Sken mps_printf(sc, "EEDP capabilities disabled.\n"); 813253549Sken } 814230592Sken 815230592Sken mps_unlock(sc); 816230592Sken 817212420Sken mpssas_register_events(sc); 818212420Skenout: 819212420Sken if (error) 820212420Sken mps_detach_sas(sc); 821212420Sken return (error); 822212420Sken} 823212420Sken 824212420Skenint 825212420Skenmps_detach_sas(struct mps_softc *sc) 826212420Sken{ 827212420Sken struct mpssas_softc *sassc; 828237683Sken struct mpssas_lun *lun, *lun_tmp; 829237683Sken struct mpssas_target *targ; 830237683Sken int i; 831212420Sken 832253460Sscottl MPS_FUNCTRACE(sc); 833212420Sken 834212420Sken if (sc->sassc == NULL) 835212420Sken return (0); 836212420Sken 837212420Sken sassc = sc->sassc; 838230592Sken mps_deregister_events(sc, sassc->mpssas_eh); 839212420Sken 840230592Sken /* 841230592Sken * Drain and free the event handling taskqueue with the lock 842230592Sken * unheld so that any parallel processing tasks drain properly 843230592Sken * without deadlocking. 844230592Sken */ 845230592Sken if (sassc->ev_tq != NULL) 846230592Sken taskqueue_free(sassc->ev_tq); 847230592Sken 848212420Sken /* Make sure CAM doesn't wedge if we had to bail out early. */ 849212420Sken mps_lock(sc); 850230592Sken 851230592Sken /* Deregister our async handler */ 852253549Sken if (sassc->path != NULL) { 853253549Sken xpt_register_async(0, mpssas_async, sc, sassc->path); 854253549Sken xpt_free_path(sassc->path); 855253549Sken sassc->path = NULL; 856253549Sken } 857230592Sken 858212420Sken if (sassc->flags & MPSSAS_IN_STARTUP) 859212420Sken xpt_release_simq(sassc->sim, 1); 860212420Sken 861212420Sken if (sassc->sim != NULL) { 862212420Sken xpt_bus_deregister(cam_sim_path(sassc->sim)); 863212420Sken cam_sim_free(sassc->sim, FALSE); 864212420Sken } 865230592Sken 866253549Sken sassc->flags |= MPSSAS_SHUTDOWN; 867212420Sken mps_unlock(sc); 868212420Sken 869212420Sken if (sassc->devq != NULL) 870212420Sken cam_simq_free(sassc->devq); 871212420Sken 872237683Sken for(i=0; i< sc->facts->MaxTargets ;i++) { 873237683Sken targ = &sassc->targets[i]; 874237683Sken SLIST_FOREACH_SAFE(lun, &targ->luns, lun_link, lun_tmp) { 875237683Sken free(lun, M_MPT2); 876237683Sken } 877237683Sken } 878212420Sken free(sassc->targets, M_MPT2); 879212420Sken free(sassc, M_MPT2); 880212420Sken sc->sassc = NULL; 881212420Sken 882212420Sken return (0); 883212420Sken} 884212420Sken 885230592Skenvoid 886212420Skenmpssas_discovery_end(struct mpssas_softc *sassc) 887212420Sken{ 888212420Sken struct mps_softc *sc = sassc->sc; 889212420Sken 890253460Sscottl MPS_FUNCTRACE(sc); 891212420Sken 892212420Sken if (sassc->flags & MPSSAS_DISCOVERY_TIMEOUT_PENDING) 893212420Sken callout_stop(&sassc->discovery_callout); 894212420Sken 895212420Sken} 896212420Sken 897212420Skenstatic void 898230592Skenmpssas_discovery_timeout(void *data) 899212420Sken{ 900230592Sken struct mpssas_softc *sassc = data; 901230592Sken struct mps_softc *sc; 902212420Sken 903230592Sken sc = sassc->sc; 904253460Sscottl MPS_FUNCTRACE(sc); 905212420Sken 906230592Sken mps_lock(sc); 907253460Sscottl mps_dprint(sc, MPS_INFO, 908230592Sken "Timeout waiting for discovery, interrupts may not be working!\n"); 909230592Sken sassc->flags &= ~MPSSAS_DISCOVERY_TIMEOUT_PENDING; 910212420Sken 911230592Sken /* Poll the hardware for events in case interrupts aren't working */ 912230592Sken mps_intr_locked(sc); 913212420Sken 914253460Sscottl mps_dprint(sassc->sc, MPS_INFO, 915230592Sken "Finished polling after discovery timeout at %d\n", ticks); 916230592Sken 917212420Sken if ((sassc->flags & MPSSAS_IN_DISCOVERY) == 0) { 918212420Sken mpssas_discovery_end(sassc); 919212420Sken } else { 920212420Sken if (sassc->discovery_timeouts < MPSSAS_MAX_DISCOVERY_TIMEOUTS) { 921212420Sken sassc->flags |= MPSSAS_DISCOVERY_TIMEOUT_PENDING; 922212420Sken callout_reset(&sassc->discovery_callout, 923212420Sken MPSSAS_DISCOVERY_TIMEOUT * hz, 924212420Sken mpssas_discovery_timeout, sassc); 925212420Sken sassc->discovery_timeouts++; 926212420Sken } else { 927212420Sken mps_dprint(sassc->sc, MPS_FAULT, 928212420Sken "Discovery timed out, continuing.\n"); 929212420Sken sassc->flags &= ~MPSSAS_IN_DISCOVERY; 930212420Sken mpssas_discovery_end(sassc); 931212420Sken } 932212420Sken } 933212420Sken 934212420Sken mps_unlock(sc); 935212420Sken} 936212420Sken 937212420Skenstatic void 938212420Skenmpssas_action(struct cam_sim *sim, union ccb *ccb) 939212420Sken{ 940212420Sken struct mpssas_softc *sassc; 941212420Sken 942212420Sken sassc = cam_sim_softc(sim); 943212420Sken 944253460Sscottl MPS_FUNCTRACE(sassc->sc); 945253460Sscottl mps_dprint(sassc->sc, MPS_TRACE, "ccb func_code 0x%x\n", 946212420Sken ccb->ccb_h.func_code); 947230592Sken mtx_assert(&sassc->sc->mps_mtx, MA_OWNED); 948212420Sken 949212420Sken switch (ccb->ccb_h.func_code) { 950212420Sken case XPT_PATH_INQ: 951212420Sken { 952212420Sken struct ccb_pathinq *cpi = &ccb->cpi; 953212420Sken 954212420Sken cpi->version_num = 1; 955212420Sken cpi->hba_inquiry = PI_SDTR_ABLE|PI_TAG_ABLE|PI_WIDE_16; 956212420Sken cpi->target_sprt = 0; 957253549Sken#if __FreeBSD_version >= 1000039 958253549Sken cpi->hba_misc = PIM_NOBUSRESET | PIM_UNMAPPED | PIM_NOSCAN; 959253549Sken#else 960248825Smav cpi->hba_misc = PIM_NOBUSRESET | PIM_UNMAPPED; 961253549Sken#endif 962212420Sken cpi->hba_eng_cnt = 0; 963212420Sken cpi->max_target = sassc->sc->facts->MaxTargets - 1; 964237683Sken cpi->max_lun = 255; 965241759Sjwd cpi->initiator_id = sassc->sc->facts->MaxTargets - 1; 966212420Sken strncpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN); 967212420Sken strncpy(cpi->hba_vid, "LSILogic", HBA_IDLEN); 968212420Sken strncpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN); 969212420Sken cpi->unit_number = cam_sim_unit(sim); 970212420Sken cpi->bus_id = cam_sim_bus(sim); 971212420Sken cpi->base_transfer_speed = 150000; 972212420Sken cpi->transport = XPORT_SAS; 973212420Sken cpi->transport_version = 0; 974212420Sken cpi->protocol = PROTO_SCSI; 975212420Sken cpi->protocol_version = SCSI_REV_SPC; 976230592Sken#if __FreeBSD_version >= 800001 977230592Sken /* 978230592Sken * XXX KDM where does this number come from? 979230592Sken */ 980230592Sken cpi->maxio = 256 * 1024; 981230592Sken#endif 982212420Sken cpi->ccb_h.status = CAM_REQ_CMP; 983212420Sken break; 984212420Sken } 985212420Sken case XPT_GET_TRAN_SETTINGS: 986212420Sken { 987212420Sken struct ccb_trans_settings *cts; 988212420Sken struct ccb_trans_settings_sas *sas; 989212420Sken struct ccb_trans_settings_scsi *scsi; 990212420Sken struct mpssas_target *targ; 991212420Sken 992212420Sken cts = &ccb->cts; 993212420Sken sas = &cts->xport_specific.sas; 994212420Sken scsi = &cts->proto_specific.scsi; 995212420Sken 996212420Sken targ = &sassc->targets[cts->ccb_h.target_id]; 997212420Sken if (targ->handle == 0x0) { 998237683Sken cts->ccb_h.status = CAM_SEL_TIMEOUT; 999212420Sken break; 1000212420Sken } 1001212420Sken 1002212420Sken cts->protocol_version = SCSI_REV_SPC2; 1003212420Sken cts->transport = XPORT_SAS; 1004212420Sken cts->transport_version = 0; 1005212420Sken 1006212420Sken sas->valid = CTS_SAS_VALID_SPEED; 1007212420Sken switch (targ->linkrate) { 1008212420Sken case 0x08: 1009212420Sken sas->bitrate = 150000; 1010212420Sken break; 1011212420Sken case 0x09: 1012212420Sken sas->bitrate = 300000; 1013212420Sken break; 1014212420Sken case 0x0a: 1015212420Sken sas->bitrate = 600000; 1016212420Sken break; 1017212420Sken default: 1018212420Sken sas->valid = 0; 1019212420Sken } 1020212420Sken 1021212420Sken cts->protocol = PROTO_SCSI; 1022212420Sken scsi->valid = CTS_SCSI_VALID_TQ; 1023212420Sken scsi->flags = CTS_SCSI_FLAGS_TAG_ENB; 1024212420Sken 1025212420Sken cts->ccb_h.status = CAM_REQ_CMP; 1026212420Sken break; 1027212420Sken } 1028212420Sken case XPT_CALC_GEOMETRY: 1029212420Sken cam_calc_geometry(&ccb->ccg, /*extended*/1); 1030212420Sken ccb->ccb_h.status = CAM_REQ_CMP; 1031212420Sken break; 1032212420Sken case XPT_RESET_DEV: 1033253460Sscottl mps_dprint(sassc->sc, MPS_XINFO, "mpssas_action XPT_RESET_DEV\n"); 1034212420Sken mpssas_action_resetdev(sassc, ccb); 1035212420Sken return; 1036212420Sken case XPT_RESET_BUS: 1037212420Sken case XPT_ABORT: 1038212420Sken case XPT_TERM_IO: 1039253460Sscottl mps_dprint(sassc->sc, MPS_XINFO, 1040253460Sscottl "mpssas_action faking success for abort or reset\n"); 1041212420Sken ccb->ccb_h.status = CAM_REQ_CMP; 1042212420Sken break; 1043212420Sken case XPT_SCSI_IO: 1044212420Sken mpssas_action_scsiio(sassc, ccb); 1045212420Sken return; 1046216088Sken#if __FreeBSD_version >= 900026 1047216088Sken case XPT_SMP_IO: 1048216088Sken mpssas_action_smpio(sassc, ccb); 1049216088Sken return; 1050230592Sken#endif 1051212420Sken default: 1052212420Sken ccb->ccb_h.status = CAM_FUNC_NOTAVAIL; 1053212420Sken break; 1054212420Sken } 1055212420Sken xpt_done(ccb); 1056212420Sken 1057212420Sken} 1058212420Sken 1059212420Skenstatic void 1060230592Skenmpssas_announce_reset(struct mps_softc *sc, uint32_t ac_code, 1061230592Sken target_id_t target_id, lun_id_t lun_id) 1062212420Sken{ 1063230592Sken path_id_t path_id = cam_sim_path(sc->sassc->sim); 1064230592Sken struct cam_path *path; 1065212420Sken 1066253460Sscottl mps_dprint(sc, MPS_XINFO, "%s code %x target %d lun %d\n", __func__, 1067230592Sken ac_code, target_id, lun_id); 1068212420Sken 1069230592Sken if (xpt_create_path(&path, NULL, 1070230592Sken path_id, target_id, lun_id) != CAM_REQ_CMP) { 1071253460Sscottl mps_dprint(sc, MPS_ERROR, "unable to create path for reset " 1072230592Sken "notification\n"); 1073230592Sken return; 1074212420Sken } 1075212420Sken 1076230592Sken xpt_async(ac_code, path, NULL); 1077230592Sken xpt_free_path(path); 1078212420Sken} 1079212420Sken 1080230592Skenstatic void 1081230592Skenmpssas_complete_all_commands(struct mps_softc *sc) 1082212420Sken{ 1083212420Sken struct mps_command *cm; 1084230592Sken int i; 1085230592Sken int completed; 1086212420Sken 1087253460Sscottl MPS_FUNCTRACE(sc); 1088230592Sken mtx_assert(&sc->mps_mtx, MA_OWNED); 1089212420Sken 1090230592Sken /* complete all commands with a NULL reply */ 1091230592Sken for (i = 1; i < sc->num_reqs; i++) { 1092230592Sken cm = &sc->commands[i]; 1093230592Sken cm->cm_reply = NULL; 1094230592Sken completed = 0; 1095230592Sken 1096230592Sken if (cm->cm_flags & MPS_CM_FLAGS_POLLED) 1097230592Sken cm->cm_flags |= MPS_CM_FLAGS_COMPLETE; 1098230592Sken 1099230592Sken if (cm->cm_complete != NULL) { 1100253460Sscottl mpssas_log_command(cm, MPS_RECOVERY, 1101230592Sken "completing cm %p state %x ccb %p for diag reset\n", 1102230592Sken cm, cm->cm_state, cm->cm_ccb); 1103230592Sken 1104230592Sken cm->cm_complete(sc, cm); 1105230592Sken completed = 1; 1106230592Sken } 1107230592Sken 1108230592Sken if (cm->cm_flags & MPS_CM_FLAGS_WAKEUP) { 1109253460Sscottl mpssas_log_command(cm, MPS_RECOVERY, 1110230592Sken "waking up cm %p state %x ccb %p for diag reset\n", 1111230592Sken cm, cm->cm_state, cm->cm_ccb); 1112230592Sken wakeup(cm); 1113230592Sken completed = 1; 1114230592Sken } 1115230592Sken 1116230592Sken if ((completed == 0) && (cm->cm_state != MPS_CM_STATE_FREE)) { 1117230592Sken /* this should never happen, but if it does, log */ 1118253460Sscottl mpssas_log_command(cm, MPS_RECOVERY, 1119230592Sken "cm %p state %x flags 0x%x ccb %p during diag " 1120230592Sken "reset\n", cm, cm->cm_state, cm->cm_flags, 1121230592Sken cm->cm_ccb); 1122230592Sken } 1123212420Sken } 1124230592Sken} 1125212420Sken 1126230592Skenvoid 1127230592Skenmpssas_handle_reinit(struct mps_softc *sc) 1128230592Sken{ 1129230592Sken int i; 1130212420Sken 1131230592Sken /* Go back into startup mode and freeze the simq, so that CAM 1132230592Sken * doesn't send any commands until after we've rediscovered all 1133230592Sken * targets and found the proper device handles for them. 1134230592Sken * 1135230592Sken * After the reset, portenable will trigger discovery, and after all 1136230592Sken * discovery-related activities have finished, the simq will be 1137230592Sken * released. 1138212802Sken */ 1139253460Sscottl mps_dprint(sc, MPS_INIT, "%s startup\n", __func__); 1140230592Sken sc->sassc->flags |= MPSSAS_IN_STARTUP; 1141230592Sken sc->sassc->flags |= MPSSAS_IN_DISCOVERY; 1142230592Sken xpt_freeze_simq(sc->sassc->sim, 1); 1143212420Sken 1144230592Sken /* notify CAM of a bus reset */ 1145230592Sken mpssas_announce_reset(sc, AC_BUS_RESET, CAM_TARGET_WILDCARD, 1146230592Sken CAM_LUN_WILDCARD); 1147212420Sken 1148230592Sken /* complete and cleanup after all outstanding commands */ 1149230592Sken mpssas_complete_all_commands(sc); 1150230592Sken 1151253460Sscottl mps_dprint(sc, MPS_INIT, 1152253460Sscottl "%s startup %u tm %u after command completion\n", 1153230592Sken __func__, sc->sassc->startup_refcount, sc->sassc->tm_count); 1154230592Sken 1155212420Sken /* 1156230592Sken * The simq was explicitly frozen above, so set the refcount to 0. 1157230592Sken * The simq will be explicitly released after port enable completes. 1158212420Sken */ 1159230592Sken sc->sassc->startup_refcount = 0; 1160230592Sken 1161230592Sken /* zero all the target handles, since they may change after the 1162230592Sken * reset, and we have to rediscover all the targets and use the new 1163230592Sken * handles. 1164230592Sken */ 1165230592Sken for (i = 0; i < sc->facts->MaxTargets; i++) { 1166230592Sken if (sc->sassc->targets[i].outstanding != 0) 1167253460Sscottl mps_dprint(sc, MPS_INIT, "target %u outstanding %u\n", 1168230592Sken i, sc->sassc->targets[i].outstanding); 1169230592Sken sc->sassc->targets[i].handle = 0x0; 1170230592Sken sc->sassc->targets[i].exp_dev_handle = 0x0; 1171230592Sken sc->sassc->targets[i].outstanding = 0; 1172230592Sken sc->sassc->targets[i].flags = MPSSAS_TARGET_INDIAGRESET; 1173230592Sken } 1174212420Sken} 1175253460Sscottl 1176230592Skenstatic void 1177230592Skenmpssas_tm_timeout(void *data) 1178230592Sken{ 1179230592Sken struct mps_command *tm = data; 1180230592Sken struct mps_softc *sc = tm->cm_sc; 1181212420Sken 1182230592Sken mtx_assert(&sc->mps_mtx, MA_OWNED); 1183230592Sken 1184253460Sscottl mpssas_log_command(tm, MPS_INFO|MPS_RECOVERY, 1185253460Sscottl "task mgmt %p timed out\n", tm); 1186230592Sken mps_reinit(sc); 1187230592Sken} 1188230592Sken 1189212420Skenstatic void 1190230592Skenmpssas_logical_unit_reset_complete(struct mps_softc *sc, struct mps_command *tm) 1191212420Sken{ 1192230592Sken MPI2_SCSI_TASK_MANAGE_REPLY *reply; 1193212420Sken MPI2_SCSI_TASK_MANAGE_REQUEST *req; 1194230592Sken unsigned int cm_count = 0; 1195230592Sken struct mps_command *cm; 1196230592Sken struct mpssas_target *targ; 1197212420Sken 1198230592Sken callout_stop(&tm->cm_callout); 1199212420Sken 1200230592Sken req = (MPI2_SCSI_TASK_MANAGE_REQUEST *)tm->cm_req; 1201230592Sken reply = (MPI2_SCSI_TASK_MANAGE_REPLY *)tm->cm_reply; 1202230592Sken targ = tm->cm_targ; 1203230592Sken 1204218812Sken /* 1205218812Sken * Currently there should be no way we can hit this case. It only 1206218812Sken * happens when we have a failure to allocate chain frames, and 1207218812Sken * task management commands don't have S/G lists. 1208253460Sscottl * XXXSL So should it be an assertion? 1209218812Sken */ 1210230592Sken if ((tm->cm_flags & MPS_CM_FLAGS_ERROR_MASK) != 0) { 1211253460Sscottl mps_dprint(sc, MPS_ERROR, "%s: cm_flags = %#x for LUN reset! " 1212230592Sken "This should not happen!\n", __func__, tm->cm_flags); 1213230592Sken mpssas_free_tm(sc, tm); 1214230592Sken return; 1215218812Sken } 1216218812Sken 1217230592Sken if (reply == NULL) { 1218253460Sscottl mpssas_log_command(tm, MPS_RECOVERY, 1219253460Sscottl "NULL reset reply for tm %p\n", tm); 1220230592Sken if ((sc->mps_flags & MPS_FLAGS_DIAGRESET) != 0) { 1221230592Sken /* this completion was due to a reset, just cleanup */ 1222230592Sken targ->flags &= ~MPSSAS_TARGET_INRESET; 1223230592Sken targ->tm = NULL; 1224230592Sken mpssas_free_tm(sc, tm); 1225230592Sken } 1226230592Sken else { 1227230592Sken /* we should have gotten a reply. */ 1228230592Sken mps_reinit(sc); 1229230592Sken } 1230230592Sken return; 1231230592Sken } 1232212420Sken 1233253460Sscottl mpssas_log_command(tm, MPS_RECOVERY, 1234230592Sken "logical unit reset status 0x%x code 0x%x count %u\n", 1235237683Sken le16toh(reply->IOCStatus), le32toh(reply->ResponseCode), 1236237683Sken le32toh(reply->TerminationCount)); 1237230592Sken 1238230592Sken /* See if there are any outstanding commands for this LUN. 1239230592Sken * This could be made more efficient by using a per-LU data 1240230592Sken * structure of some sort. 1241230592Sken */ 1242230592Sken TAILQ_FOREACH(cm, &targ->commands, cm_link) { 1243230592Sken if (cm->cm_lun == tm->cm_lun) 1244230592Sken cm_count++; 1245230592Sken } 1246230592Sken 1247230592Sken if (cm_count == 0) { 1248253460Sscottl mpssas_log_command(tm, MPS_RECOVERY|MPS_INFO, 1249230592Sken "logical unit %u finished recovery after reset\n", 1250230592Sken tm->cm_lun, tm); 1251230592Sken 1252230592Sken mpssas_announce_reset(sc, AC_SENT_BDR, tm->cm_targ->tid, 1253230592Sken tm->cm_lun); 1254230592Sken 1255230592Sken /* we've finished recovery for this logical unit. check and 1256230592Sken * see if some other logical unit has a timedout command 1257230592Sken * that needs to be processed. 1258230592Sken */ 1259230592Sken cm = TAILQ_FIRST(&targ->timedout_commands); 1260230592Sken if (cm) { 1261230592Sken mpssas_send_abort(sc, tm, cm); 1262230592Sken } 1263230592Sken else { 1264230592Sken targ->tm = NULL; 1265230592Sken mpssas_free_tm(sc, tm); 1266230592Sken } 1267230592Sken } 1268230592Sken else { 1269230592Sken /* if we still have commands for this LUN, the reset 1270230592Sken * effectively failed, regardless of the status reported. 1271230592Sken * Escalate to a target reset. 1272230592Sken */ 1273253460Sscottl mpssas_log_command(tm, MPS_RECOVERY, 1274230592Sken "logical unit reset complete for tm %p, but still have %u command(s)\n", 1275230592Sken tm, cm_count); 1276230592Sken mpssas_send_reset(sc, tm, 1277230592Sken MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET); 1278230592Sken } 1279212420Sken} 1280212420Sken 1281212420Skenstatic void 1282230592Skenmpssas_target_reset_complete(struct mps_softc *sc, struct mps_command *tm) 1283212420Sken{ 1284230592Sken MPI2_SCSI_TASK_MANAGE_REPLY *reply; 1285230592Sken MPI2_SCSI_TASK_MANAGE_REQUEST *req; 1286230592Sken struct mpssas_target *targ; 1287212420Sken 1288230592Sken callout_stop(&tm->cm_callout); 1289230592Sken 1290230592Sken req = (MPI2_SCSI_TASK_MANAGE_REQUEST *)tm->cm_req; 1291230592Sken reply = (MPI2_SCSI_TASK_MANAGE_REPLY *)tm->cm_reply; 1292230592Sken targ = tm->cm_targ; 1293230592Sken 1294230592Sken /* 1295230592Sken * Currently there should be no way we can hit this case. It only 1296230592Sken * happens when we have a failure to allocate chain frames, and 1297230592Sken * task management commands don't have S/G lists. 1298230592Sken */ 1299230592Sken if ((tm->cm_flags & MPS_CM_FLAGS_ERROR_MASK) != 0) { 1300253460Sscottl mps_dprint(sc, MPS_ERROR,"%s: cm_flags = %#x for target reset! " 1301230592Sken "This should not happen!\n", __func__, tm->cm_flags); 1302230592Sken mpssas_free_tm(sc, tm); 1303212420Sken return; 1304212420Sken } 1305212420Sken 1306230592Sken if (reply == NULL) { 1307253460Sscottl mpssas_log_command(tm, MPS_RECOVERY, 1308253460Sscottl "NULL reset reply for tm %p\n", tm); 1309230592Sken if ((sc->mps_flags & MPS_FLAGS_DIAGRESET) != 0) { 1310230592Sken /* this completion was due to a reset, just cleanup */ 1311230592Sken targ->flags &= ~MPSSAS_TARGET_INRESET; 1312230592Sken targ->tm = NULL; 1313230592Sken mpssas_free_tm(sc, tm); 1314230592Sken } 1315230592Sken else { 1316230592Sken /* we should have gotten a reply. */ 1317230592Sken mps_reinit(sc); 1318230592Sken } 1319230592Sken return; 1320230592Sken } 1321212420Sken 1322253460Sscottl mpssas_log_command(tm, MPS_RECOVERY, 1323230592Sken "target reset status 0x%x code 0x%x count %u\n", 1324237683Sken le16toh(reply->IOCStatus), le32toh(reply->ResponseCode), 1325237683Sken le32toh(reply->TerminationCount)); 1326212420Sken 1327230592Sken targ->flags &= ~MPSSAS_TARGET_INRESET; 1328212420Sken 1329230592Sken if (targ->outstanding == 0) { 1330230592Sken /* we've finished recovery for this target and all 1331230592Sken * of its logical units. 1332230592Sken */ 1333253460Sscottl mpssas_log_command(tm, MPS_RECOVERY|MPS_INFO, 1334230592Sken "recovery finished after target reset\n"); 1335213535Sken 1336230592Sken mpssas_announce_reset(sc, AC_SENT_BDR, tm->cm_targ->tid, 1337230592Sken CAM_LUN_WILDCARD); 1338230592Sken 1339230592Sken targ->tm = NULL; 1340230592Sken mpssas_free_tm(sc, tm); 1341230592Sken } 1342230592Sken else { 1343230592Sken /* after a target reset, if this target still has 1344230592Sken * outstanding commands, the reset effectively failed, 1345230592Sken * regardless of the status reported. escalate. 1346230592Sken */ 1347253460Sscottl mpssas_log_command(tm, MPS_RECOVERY, 1348230592Sken "target reset complete for tm %p, but still have %u command(s)\n", 1349230592Sken tm, targ->outstanding); 1350230592Sken mps_reinit(sc); 1351230592Sken } 1352213535Sken} 1353213535Sken 1354230592Sken#define MPS_RESET_TIMEOUT 30 1355230592Sken 1356213535Skenstatic int 1357230592Skenmpssas_send_reset(struct mps_softc *sc, struct mps_command *tm, uint8_t type) 1358213535Sken{ 1359230592Sken MPI2_SCSI_TASK_MANAGE_REQUEST *req; 1360230592Sken struct mpssas_target *target; 1361230592Sken int err; 1362213535Sken 1363230592Sken target = tm->cm_targ; 1364230592Sken if (target->handle == 0) { 1365253460Sscottl mps_dprint(sc, MPS_ERROR,"%s null devhandle for target_id %d\n", 1366230592Sken __func__, target->tid); 1367230592Sken return -1; 1368230592Sken } 1369213535Sken 1370230592Sken req = (MPI2_SCSI_TASK_MANAGE_REQUEST *)tm->cm_req; 1371237683Sken req->DevHandle = htole16(target->handle); 1372230592Sken req->Function = MPI2_FUNCTION_SCSI_TASK_MGMT; 1373230592Sken req->TaskType = type; 1374213535Sken 1375230592Sken if (type == MPI2_SCSITASKMGMT_TASKTYPE_LOGICAL_UNIT_RESET) { 1376230592Sken /* XXX Need to handle invalid LUNs */ 1377230592Sken MPS_SET_LUN(req->LUN, tm->cm_lun); 1378230592Sken tm->cm_targ->logical_unit_resets++; 1379253460Sscottl mpssas_log_command(tm, MPS_RECOVERY|MPS_INFO, 1380253460Sscottl "sending logical unit reset\n"); 1381230592Sken tm->cm_complete = mpssas_logical_unit_reset_complete; 1382230592Sken } 1383230592Sken else if (type == MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET) { 1384230592Sken /* Target reset method = SAS Hard Link Reset / SATA Link Reset */ 1385230592Sken req->MsgFlags = MPI2_SCSITASKMGMT_MSGFLAGS_LINK_RESET; 1386230592Sken tm->cm_targ->target_resets++; 1387230592Sken tm->cm_targ->flags |= MPSSAS_TARGET_INRESET; 1388253460Sscottl mpssas_log_command(tm, MPS_RECOVERY|MPS_INFO, 1389253460Sscottl "sending target reset\n"); 1390230592Sken tm->cm_complete = mpssas_target_reset_complete; 1391230592Sken } 1392230592Sken else { 1393253460Sscottl mps_dprint(sc, MPS_ERROR, "unexpected reset type 0x%x\n", type); 1394230592Sken return -1; 1395230592Sken } 1396230592Sken 1397230592Sken tm->cm_data = NULL; 1398230592Sken tm->cm_desc.HighPriority.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_HIGH_PRIORITY; 1399230592Sken tm->cm_complete_data = (void *)tm; 1400230592Sken 1401230592Sken callout_reset(&tm->cm_callout, MPS_RESET_TIMEOUT * hz, 1402230592Sken mpssas_tm_timeout, tm); 1403230592Sken 1404230592Sken err = mps_map_command(sc, tm); 1405230592Sken if (err) 1406253460Sscottl mpssas_log_command(tm, MPS_RECOVERY, 1407230592Sken "error %d sending reset type %u\n", 1408230592Sken err, type); 1409230592Sken 1410230592Sken return err; 1411213535Sken} 1412213535Sken 1413230592Sken 1414213535Skenstatic void 1415230592Skenmpssas_abort_complete(struct mps_softc *sc, struct mps_command *tm) 1416213535Sken{ 1417230592Sken struct mps_command *cm; 1418230592Sken MPI2_SCSI_TASK_MANAGE_REPLY *reply; 1419230592Sken MPI2_SCSI_TASK_MANAGE_REQUEST *req; 1420230592Sken struct mpssas_target *targ; 1421213535Sken 1422230592Sken callout_stop(&tm->cm_callout); 1423213535Sken 1424230592Sken req = (MPI2_SCSI_TASK_MANAGE_REQUEST *)tm->cm_req; 1425230592Sken reply = (MPI2_SCSI_TASK_MANAGE_REPLY *)tm->cm_reply; 1426230592Sken targ = tm->cm_targ; 1427213535Sken 1428212772Sken /* 1429230592Sken * Currently there should be no way we can hit this case. It only 1430230592Sken * happens when we have a failure to allocate chain frames, and 1431230592Sken * task management commands don't have S/G lists. 1432212772Sken */ 1433230592Sken if ((tm->cm_flags & MPS_CM_FLAGS_ERROR_MASK) != 0) { 1434253460Sscottl mpssas_log_command(tm, MPS_RECOVERY, 1435230592Sken "cm_flags = %#x for abort %p TaskMID %u!\n", 1436237683Sken tm->cm_flags, tm, le16toh(req->TaskMID)); 1437230592Sken mpssas_free_tm(sc, tm); 1438230592Sken return; 1439230592Sken } 1440212772Sken 1441230592Sken if (reply == NULL) { 1442253460Sscottl mpssas_log_command(tm, MPS_RECOVERY, 1443230592Sken "NULL abort reply for tm %p TaskMID %u\n", 1444237683Sken tm, le16toh(req->TaskMID)); 1445230592Sken if ((sc->mps_flags & MPS_FLAGS_DIAGRESET) != 0) { 1446230592Sken /* this completion was due to a reset, just cleanup */ 1447230592Sken targ->tm = NULL; 1448230592Sken mpssas_free_tm(sc, tm); 1449230592Sken } 1450230592Sken else { 1451230592Sken /* we should have gotten a reply. */ 1452230592Sken mps_reinit(sc); 1453230592Sken } 1454230592Sken return; 1455230592Sken } 1456212420Sken 1457253460Sscottl mpssas_log_command(tm, MPS_RECOVERY, 1458230592Sken "abort TaskMID %u status 0x%x code 0x%x count %u\n", 1459237683Sken le16toh(req->TaskMID), 1460237683Sken le16toh(reply->IOCStatus), le32toh(reply->ResponseCode), 1461237683Sken le32toh(reply->TerminationCount)); 1462213535Sken 1463230592Sken cm = TAILQ_FIRST(&tm->cm_targ->timedout_commands); 1464230592Sken if (cm == NULL) { 1465230592Sken /* if there are no more timedout commands, we're done with 1466230592Sken * error recovery for this target. 1467213535Sken */ 1468253460Sscottl mpssas_log_command(tm, MPS_RECOVERY, 1469230592Sken "finished recovery after aborting TaskMID %u\n", 1470237683Sken le16toh(req->TaskMID)); 1471230592Sken 1472230592Sken targ->tm = NULL; 1473230592Sken mpssas_free_tm(sc, tm); 1474212420Sken } 1475237683Sken else if (le16toh(req->TaskMID) != cm->cm_desc.Default.SMID) { 1476230592Sken /* abort success, but we have more timedout commands to abort */ 1477253460Sscottl mpssas_log_command(tm, MPS_RECOVERY, 1478230592Sken "continuing recovery after aborting TaskMID %u\n", 1479237683Sken le16toh(req->TaskMID)); 1480230592Sken 1481230592Sken mpssas_send_abort(sc, tm, cm); 1482230592Sken } 1483230592Sken else { 1484230592Sken /* we didn't get a command completion, so the abort 1485230592Sken * failed as far as we're concerned. escalate. 1486230592Sken */ 1487253460Sscottl mpssas_log_command(tm, MPS_RECOVERY, 1488230592Sken "abort failed for TaskMID %u tm %p\n", 1489237683Sken le16toh(req->TaskMID), tm); 1490230592Sken 1491230592Sken mpssas_send_reset(sc, tm, 1492230592Sken MPI2_SCSITASKMGMT_TASKTYPE_LOGICAL_UNIT_RESET); 1493230592Sken } 1494213535Sken} 1495212420Sken 1496230592Sken#define MPS_ABORT_TIMEOUT 5 1497230592Sken 1498230592Skenstatic int 1499230592Skenmpssas_send_abort(struct mps_softc *sc, struct mps_command *tm, struct mps_command *cm) 1500213535Sken{ 1501230592Sken MPI2_SCSI_TASK_MANAGE_REQUEST *req; 1502230592Sken struct mpssas_target *targ; 1503230592Sken int err; 1504212420Sken 1505230592Sken targ = cm->cm_targ; 1506230592Sken if (targ->handle == 0) { 1507253460Sscottl mps_dprint(sc, MPS_ERROR,"%s null devhandle for target_id %d\n", 1508230592Sken __func__, cm->cm_ccb->ccb_h.target_id); 1509230592Sken return -1; 1510230592Sken } 1511213535Sken 1512253460Sscottl mpssas_log_command(tm, MPS_RECOVERY|MPS_INFO, 1513253460Sscottl "Aborting command %p\n", cm); 1514253460Sscottl 1515230592Sken req = (MPI2_SCSI_TASK_MANAGE_REQUEST *)tm->cm_req; 1516237683Sken req->DevHandle = htole16(targ->handle); 1517230592Sken req->Function = MPI2_FUNCTION_SCSI_TASK_MGMT; 1518230592Sken req->TaskType = MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK; 1519213535Sken 1520230592Sken /* XXX Need to handle invalid LUNs */ 1521230592Sken MPS_SET_LUN(req->LUN, cm->cm_ccb->ccb_h.target_lun); 1522212420Sken 1523237683Sken req->TaskMID = htole16(cm->cm_desc.Default.SMID); 1524213535Sken 1525230592Sken tm->cm_data = NULL; 1526230592Sken tm->cm_desc.HighPriority.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_HIGH_PRIORITY; 1527230592Sken tm->cm_complete = mpssas_abort_complete; 1528230592Sken tm->cm_complete_data = (void *)tm; 1529230592Sken tm->cm_targ = cm->cm_targ; 1530230592Sken tm->cm_lun = cm->cm_lun; 1531213535Sken 1532230592Sken callout_reset(&tm->cm_callout, MPS_ABORT_TIMEOUT * hz, 1533230592Sken mpssas_tm_timeout, tm); 1534213535Sken 1535230592Sken targ->aborts++; 1536213535Sken 1537230592Sken err = mps_map_command(sc, tm); 1538230592Sken if (err) 1539253460Sscottl mpssas_log_command(tm, MPS_RECOVERY, 1540230592Sken "error %d sending abort for cm %p SMID %u\n", 1541230592Sken err, cm, req->TaskMID); 1542230592Sken return err; 1543230592Sken} 1544213535Sken 1545213535Sken 1546230592Skenstatic void 1547230592Skenmpssas_scsiio_timeout(void *data) 1548230592Sken{ 1549230592Sken struct mps_softc *sc; 1550230592Sken struct mps_command *cm; 1551230592Sken struct mpssas_target *targ; 1552213535Sken 1553230592Sken cm = (struct mps_command *)data; 1554230592Sken sc = cm->cm_sc; 1555213535Sken 1556253460Sscottl MPS_FUNCTRACE(sc); 1557230592Sken mtx_assert(&sc->mps_mtx, MA_OWNED); 1558213535Sken 1559253460Sscottl mps_dprint(sc, MPS_XINFO, "Timeout checking cm %p\n", sc); 1560213535Sken 1561230592Sken /* 1562230592Sken * Run the interrupt handler to make sure it's not pending. This 1563230592Sken * isn't perfect because the command could have already completed 1564230592Sken * and been re-used, though this is unlikely. 1565230592Sken */ 1566230592Sken mps_intr_locked(sc); 1567230592Sken if (cm->cm_state == MPS_CM_STATE_FREE) { 1568253460Sscottl mpssas_log_command(cm, MPS_XINFO, 1569253460Sscottl "SCSI command %p almost timed out\n", cm); 1570230592Sken return; 1571230592Sken } 1572213535Sken 1573230592Sken if (cm->cm_ccb == NULL) { 1574253460Sscottl mps_dprint(sc, MPS_ERROR, "command timeout with NULL ccb\n"); 1575230592Sken return; 1576230592Sken } 1577213535Sken 1578253460Sscottl mpssas_log_command(cm, MPS_INFO, "command timeout cm %p ccb %p\n", 1579230592Sken cm, cm->cm_ccb); 1580213535Sken 1581230592Sken targ = cm->cm_targ; 1582230592Sken targ->timeouts++; 1583213535Sken 1584230592Sken /* XXX first, check the firmware state, to see if it's still 1585230592Sken * operational. if not, do a diag reset. 1586230592Sken */ 1587230592Sken 1588230592Sken cm->cm_ccb->ccb_h.status = CAM_CMD_TIMEOUT; 1589230592Sken cm->cm_state = MPS_CM_STATE_TIMEDOUT; 1590230592Sken TAILQ_INSERT_TAIL(&targ->timedout_commands, cm, cm_recovery); 1591230592Sken 1592230592Sken if (targ->tm != NULL) { 1593230592Sken /* target already in recovery, just queue up another 1594230592Sken * timedout command to be processed later. 1595230592Sken */ 1596253460Sscottl mps_dprint(sc, MPS_RECOVERY, 1597253460Sscottl "queued timedout cm %p for processing by tm %p\n", 1598230592Sken cm, targ->tm); 1599213535Sken } 1600230592Sken else if ((targ->tm = mpssas_alloc_tm(sc)) != NULL) { 1601253460Sscottl mps_dprint(sc, MPS_RECOVERY, "timedout cm %p allocated tm %p\n", 1602230592Sken cm, targ->tm); 1603213535Sken 1604230592Sken /* start recovery by aborting the first timedout command */ 1605230592Sken mpssas_send_abort(sc, targ->tm, cm); 1606230592Sken } 1607230592Sken else { 1608230592Sken /* XXX queue this target up for recovery once a TM becomes 1609230592Sken * available. The firmware only has a limited number of 1610230592Sken * HighPriority credits for the high priority requests used 1611230592Sken * for task management, and we ran out. 1612230592Sken * 1613230592Sken * Isilon: don't worry about this for now, since we have 1614230592Sken * more credits than disks in an enclosure, and limit 1615230592Sken * ourselves to one TM per target for recovery. 1616230592Sken */ 1617253460Sscottl mps_dprint(sc, MPS_RECOVERY, 1618253460Sscottl "timedout cm %p failed to allocate a tm\n", cm); 1619230592Sken } 1620230592Sken 1621213535Sken} 1622213535Sken 1623212420Skenstatic void 1624212420Skenmpssas_action_scsiio(struct mpssas_softc *sassc, union ccb *ccb) 1625212420Sken{ 1626212420Sken MPI2_SCSI_IO_REQUEST *req; 1627212420Sken struct ccb_scsiio *csio; 1628212420Sken struct mps_softc *sc; 1629212420Sken struct mpssas_target *targ; 1630230592Sken struct mpssas_lun *lun; 1631212420Sken struct mps_command *cm; 1632230592Sken uint8_t i, lba_byte, *ref_tag_addr; 1633230592Sken uint16_t eedp_flags; 1634237683Sken uint32_t mpi_control; 1635212420Sken 1636212420Sken sc = sassc->sc; 1637253460Sscottl MPS_FUNCTRACE(sc); 1638230592Sken mtx_assert(&sc->mps_mtx, MA_OWNED); 1639212420Sken 1640212420Sken csio = &ccb->csio; 1641212420Sken targ = &sassc->targets[csio->ccb_h.target_id]; 1642253460Sscottl mps_dprint(sc, MPS_TRACE, "ccb %p target flag %x\n", ccb, targ->flags); 1643212420Sken if (targ->handle == 0x0) { 1644253460Sscottl mps_dprint(sc, MPS_ERROR, "%s NULL handle for target %u\n", 1645230592Sken __func__, csio->ccb_h.target_id); 1646237683Sken csio->ccb_h.status = CAM_SEL_TIMEOUT; 1647212420Sken xpt_done(ccb); 1648212420Sken return; 1649212420Sken } 1650231240Sken if (targ->flags & MPS_TARGET_FLAGS_RAID_COMPONENT) { 1651253550Sken mps_dprint(sc, MPS_ERROR, "%s Raid component no SCSI IO " 1652253550Sken "supported %u\n", __func__, csio->ccb_h.target_id); 1653231240Sken csio->ccb_h.status = CAM_TID_INVALID; 1654231240Sken xpt_done(ccb); 1655231240Sken return; 1656231240Sken } 1657230592Sken /* 1658253550Sken * Sometimes, it is possible to get a command that is not "In 1659253550Sken * Progress" and was actually aborted by the upper layer. Check for 1660253550Sken * this here and complete the command without error. 1661253550Sken */ 1662253550Sken if (ccb->ccb_h.status != CAM_REQ_INPROG) { 1663253550Sken mps_dprint(sc, MPS_TRACE, "%s Command is not in progress for " 1664253550Sken "target %u\n", __func__, csio->ccb_h.target_id); 1665253550Sken xpt_done(ccb); 1666253550Sken return; 1667253550Sken } 1668253550Sken /* 1669230592Sken * If devinfo is 0 this will be a volume. In that case don't tell CAM 1670230592Sken * that the volume has timed out. We want volumes to be enumerated 1671230592Sken * until they are deleted/removed, not just failed. 1672230592Sken */ 1673230592Sken if (targ->flags & MPSSAS_TARGET_INREMOVAL) { 1674230592Sken if (targ->devinfo == 0) 1675230592Sken csio->ccb_h.status = CAM_REQ_CMP; 1676230592Sken else 1677230592Sken csio->ccb_h.status = CAM_SEL_TIMEOUT; 1678230592Sken xpt_done(ccb); 1679230592Sken return; 1680230592Sken } 1681212420Sken 1682230592Sken if ((sc->mps_flags & MPS_FLAGS_SHUTDOWN) != 0) { 1683253460Sscottl mps_dprint(sc, MPS_INFO, "%s shutting down\n", __func__); 1684230592Sken csio->ccb_h.status = CAM_TID_INVALID; 1685230592Sken xpt_done(ccb); 1686230592Sken return; 1687230592Sken } 1688230592Sken 1689212420Sken cm = mps_alloc_command(sc); 1690212420Sken if (cm == NULL) { 1691212420Sken if ((sassc->flags & MPSSAS_QUEUE_FROZEN) == 0) { 1692212420Sken xpt_freeze_simq(sassc->sim, 1); 1693212420Sken sassc->flags |= MPSSAS_QUEUE_FROZEN; 1694212420Sken } 1695212420Sken ccb->ccb_h.status &= ~CAM_SIM_QUEUED; 1696212420Sken ccb->ccb_h.status |= CAM_REQUEUE_REQ; 1697212420Sken xpt_done(ccb); 1698212420Sken return; 1699212420Sken } 1700212420Sken 1701212420Sken req = (MPI2_SCSI_IO_REQUEST *)cm->cm_req; 1702218812Sken bzero(req, sizeof(*req)); 1703237683Sken req->DevHandle = htole16(targ->handle); 1704212420Sken req->Function = MPI2_FUNCTION_SCSI_IO_REQUEST; 1705212420Sken req->MsgFlags = 0; 1706237683Sken req->SenseBufferLowAddress = htole32(cm->cm_sense_busaddr); 1707212420Sken req->SenseBufferLength = MPS_SENSE_LEN; 1708212420Sken req->SGLFlags = 0; 1709212420Sken req->ChainOffset = 0; 1710212420Sken req->SGLOffset0 = 24; /* 32bit word offset to the SGL */ 1711212420Sken req->SGLOffset1= 0; 1712212420Sken req->SGLOffset2= 0; 1713212420Sken req->SGLOffset3= 0; 1714212420Sken req->SkipCount = 0; 1715237683Sken req->DataLength = htole32(csio->dxfer_len); 1716212420Sken req->BidirectionalDataLength = 0; 1717237683Sken req->IoFlags = htole16(csio->cdb_len); 1718212420Sken req->EEDPFlags = 0; 1719212420Sken 1720212420Sken /* Note: BiDirectional transfers are not supported */ 1721212420Sken switch (csio->ccb_h.flags & CAM_DIR_MASK) { 1722212420Sken case CAM_DIR_IN: 1723237683Sken mpi_control = MPI2_SCSIIO_CONTROL_READ; 1724212420Sken cm->cm_flags |= MPS_CM_FLAGS_DATAIN; 1725212420Sken break; 1726212420Sken case CAM_DIR_OUT: 1727237683Sken mpi_control = MPI2_SCSIIO_CONTROL_WRITE; 1728212420Sken cm->cm_flags |= MPS_CM_FLAGS_DATAOUT; 1729212420Sken break; 1730212420Sken case CAM_DIR_NONE: 1731212420Sken default: 1732237683Sken mpi_control = MPI2_SCSIIO_CONTROL_NODATATRANSFER; 1733212420Sken break; 1734212420Sken } 1735237683Sken 1736253550Sken if (csio->cdb_len == 32) 1737237683Sken mpi_control |= 4 << MPI2_SCSIIO_CONTROL_ADDCDBLEN_SHIFT; 1738212420Sken /* 1739212420Sken * It looks like the hardware doesn't require an explicit tag 1740212420Sken * number for each transaction. SAM Task Management not supported 1741212420Sken * at the moment. 1742212420Sken */ 1743212420Sken switch (csio->tag_action) { 1744212420Sken case MSG_HEAD_OF_Q_TAG: 1745237683Sken mpi_control |= MPI2_SCSIIO_CONTROL_HEADOFQ; 1746212420Sken break; 1747212420Sken case MSG_ORDERED_Q_TAG: 1748237683Sken mpi_control |= MPI2_SCSIIO_CONTROL_ORDEREDQ; 1749212420Sken break; 1750212420Sken case MSG_ACA_TASK: 1751237683Sken mpi_control |= MPI2_SCSIIO_CONTROL_ACAQ; 1752212420Sken break; 1753212420Sken case CAM_TAG_ACTION_NONE: 1754212420Sken case MSG_SIMPLE_Q_TAG: 1755212420Sken default: 1756237683Sken mpi_control |= MPI2_SCSIIO_CONTROL_SIMPLEQ; 1757212420Sken break; 1758212420Sken } 1759237683Sken mpi_control |= sc->mapping_table[csio->ccb_h.target_id].TLR_bits; 1760237683Sken req->Control = htole32(mpi_control); 1761216368Sken if (MPS_SET_LUN(req->LUN, csio->ccb_h.target_lun) != 0) { 1762212420Sken mps_free_command(sc, cm); 1763212420Sken ccb->ccb_h.status = CAM_LUN_INVALID; 1764212420Sken xpt_done(ccb); 1765212420Sken return; 1766212420Sken } 1767212420Sken 1768212420Sken if (csio->ccb_h.flags & CAM_CDB_POINTER) 1769212420Sken bcopy(csio->cdb_io.cdb_ptr, &req->CDB.CDB32[0], csio->cdb_len); 1770212420Sken else 1771212420Sken bcopy(csio->cdb_io.cdb_bytes, &req->CDB.CDB32[0],csio->cdb_len); 1772237683Sken req->IoFlags = htole16(csio->cdb_len); 1773212420Sken 1774216088Sken /* 1775230592Sken * Check if EEDP is supported and enabled. If it is then check if the 1776230592Sken * SCSI opcode could be using EEDP. If so, make sure the LUN exists and 1777230592Sken * is formatted for EEDP support. If all of this is true, set CDB up 1778230592Sken * for EEDP transfer. 1779216088Sken */ 1780230592Sken eedp_flags = op_code_prot[req->CDB.CDB32[0]]; 1781230592Sken if (sc->eedp_enabled && eedp_flags) { 1782230592Sken SLIST_FOREACH(lun, &targ->luns, lun_link) { 1783230592Sken if (lun->lun_id == csio->ccb_h.target_lun) { 1784230592Sken break; 1785230592Sken } 1786230592Sken } 1787230592Sken 1788230592Sken if ((lun != NULL) && (lun->eedp_formatted)) { 1789237683Sken req->EEDPBlockSize = htole16(lun->eedp_block_size); 1790230592Sken eedp_flags |= (MPI2_SCSIIO_EEDPFLAGS_INC_PRI_REFTAG | 1791230592Sken MPI2_SCSIIO_EEDPFLAGS_CHECK_REFTAG | 1792230592Sken MPI2_SCSIIO_EEDPFLAGS_CHECK_GUARD); 1793237683Sken req->EEDPFlags = htole16(eedp_flags); 1794230592Sken 1795230592Sken /* 1796230592Sken * If CDB less than 32, fill in Primary Ref Tag with 1797230592Sken * low 4 bytes of LBA. If CDB is 32, tag stuff is 1798230592Sken * already there. Also, set protection bit. FreeBSD 1799230592Sken * currently does not support CDBs bigger than 16, but 1800230592Sken * the code doesn't hurt, and will be here for the 1801230592Sken * future. 1802230592Sken */ 1803230592Sken if (csio->cdb_len != 32) { 1804230592Sken lba_byte = (csio->cdb_len == 16) ? 6 : 2; 1805230592Sken ref_tag_addr = (uint8_t *)&req->CDB.EEDP32. 1806230592Sken PrimaryReferenceTag; 1807230592Sken for (i = 0; i < 4; i++) { 1808230592Sken *ref_tag_addr = 1809230592Sken req->CDB.CDB32[lba_byte + i]; 1810230592Sken ref_tag_addr++; 1811230592Sken } 1812237683Sken req->CDB.EEDP32.PrimaryReferenceTag = 1813237683Sken htole32(req->CDB.EEDP32.PrimaryReferenceTag); 1814230592Sken req->CDB.EEDP32.PrimaryApplicationTagMask = 1815230592Sken 0xFFFF; 1816230592Sken req->CDB.CDB32[1] = (req->CDB.CDB32[1] & 0x1F) | 1817230592Sken 0x20; 1818230592Sken } else { 1819230592Sken eedp_flags |= 1820230592Sken MPI2_SCSIIO_EEDPFLAGS_INC_PRI_APPTAG; 1821237683Sken req->EEDPFlags = htole16(eedp_flags); 1822230592Sken req->CDB.CDB32[10] = (req->CDB.CDB32[10] & 1823230592Sken 0x1F) | 0x20; 1824230592Sken } 1825230592Sken } 1826230592Sken } 1827230592Sken 1828212420Sken cm->cm_length = csio->dxfer_len; 1829246713Skib if (cm->cm_length != 0) { 1830246713Skib cm->cm_data = ccb; 1831246713Skib cm->cm_flags |= MPS_CM_FLAGS_USE_CCB; 1832246713Skib } else { 1833246713Skib cm->cm_data = NULL; 1834246713Skib } 1835212420Sken cm->cm_sge = &req->SGL; 1836212420Sken cm->cm_sglsize = (32 - 24) * 4; 1837212420Sken cm->cm_desc.SCSIIO.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_SCSI_IO; 1838237683Sken cm->cm_desc.SCSIIO.DevHandle = htole16(targ->handle); 1839212420Sken cm->cm_complete = mpssas_scsiio_complete; 1840212420Sken cm->cm_complete_data = ccb; 1841212420Sken cm->cm_targ = targ; 1842230592Sken cm->cm_lun = csio->ccb_h.target_lun; 1843230592Sken cm->cm_ccb = ccb; 1844212420Sken 1845230592Sken /* 1846230592Sken * If HBA is a WD and the command is not for a retry, try to build a 1847230592Sken * direct I/O message. If failed, or the command is for a retry, send 1848230592Sken * the I/O to the IR volume itself. 1849230592Sken */ 1850230592Sken if (sc->WD_valid_config) { 1851230592Sken if (ccb->ccb_h.status != MPS_WD_RETRY) { 1852230592Sken mpssas_direct_drive_io(sassc, cm, ccb); 1853230592Sken } else { 1854230592Sken ccb->ccb_h.status = CAM_REQ_INPROG; 1855230592Sken } 1856230592Sken } 1857218812Sken 1858212420Sken callout_reset(&cm->cm_callout, (ccb->ccb_h.timeout * hz) / 1000, 1859212420Sken mpssas_scsiio_timeout, cm); 1860212420Sken 1861230592Sken targ->issued++; 1862230592Sken targ->outstanding++; 1863230592Sken TAILQ_INSERT_TAIL(&targ->commands, cm, cm_link); 1864253550Sken ccb->ccb_h.status |= CAM_SIM_QUEUED; 1865230592Sken 1866253460Sscottl mpssas_log_command(cm, MPS_XINFO, "%s cm %p ccb %p outstanding %u\n", 1867253460Sscottl __func__, cm, ccb, targ->outstanding); 1868230592Sken 1869212420Sken mps_map_command(sc, cm); 1870212420Sken return; 1871212420Sken} 1872212420Sken 1873212420Skenstatic void 1874231240Skenmps_response_code(struct mps_softc *sc, u8 response_code) 1875231240Sken{ 1876231240Sken char *desc; 1877231240Sken 1878231240Sken switch (response_code) { 1879231240Sken case MPI2_SCSITASKMGMT_RSP_TM_COMPLETE: 1880231240Sken desc = "task management request completed"; 1881231240Sken break; 1882231240Sken case MPI2_SCSITASKMGMT_RSP_INVALID_FRAME: 1883231240Sken desc = "invalid frame"; 1884231240Sken break; 1885231240Sken case MPI2_SCSITASKMGMT_RSP_TM_NOT_SUPPORTED: 1886231240Sken desc = "task management request not supported"; 1887231240Sken break; 1888231240Sken case MPI2_SCSITASKMGMT_RSP_TM_FAILED: 1889231240Sken desc = "task management request failed"; 1890231240Sken break; 1891231240Sken case MPI2_SCSITASKMGMT_RSP_TM_SUCCEEDED: 1892231240Sken desc = "task management request succeeded"; 1893231240Sken break; 1894231240Sken case MPI2_SCSITASKMGMT_RSP_TM_INVALID_LUN: 1895231240Sken desc = "invalid lun"; 1896231240Sken break; 1897231240Sken case 0xA: 1898231240Sken desc = "overlapped tag attempted"; 1899231240Sken break; 1900231240Sken case MPI2_SCSITASKMGMT_RSP_IO_QUEUED_ON_IOC: 1901231240Sken desc = "task queued, however not sent to target"; 1902231240Sken break; 1903231240Sken default: 1904231240Sken desc = "unknown"; 1905231240Sken break; 1906231240Sken } 1907253460Sscottl mps_dprint(sc, MPS_XINFO, "response_code(0x%01x): %s\n", 1908231240Sken response_code, desc); 1909231240Sken} 1910231240Sken/** 1911231240Sken * mps_sc_failed_io_info - translated non-succesfull SCSI_IO request 1912231240Sken */ 1913231240Skenstatic void 1914231240Skenmps_sc_failed_io_info(struct mps_softc *sc, struct ccb_scsiio *csio, 1915231240Sken Mpi2SCSIIOReply_t *mpi_reply) 1916231240Sken{ 1917231240Sken u32 response_info; 1918231240Sken u8 *response_bytes; 1919231240Sken u16 ioc_status = le16toh(mpi_reply->IOCStatus) & 1920231240Sken MPI2_IOCSTATUS_MASK; 1921231240Sken u8 scsi_state = mpi_reply->SCSIState; 1922231240Sken u8 scsi_status = mpi_reply->SCSIStatus; 1923231240Sken char *desc_ioc_state = NULL; 1924231240Sken char *desc_scsi_status = NULL; 1925231240Sken char *desc_scsi_state = sc->tmp_string; 1926231240Sken u32 log_info = le32toh(mpi_reply->IOCLogInfo); 1927231240Sken 1928231240Sken if (log_info == 0x31170000) 1929231240Sken return; 1930231240Sken 1931231240Sken switch (ioc_status) { 1932231240Sken case MPI2_IOCSTATUS_SUCCESS: 1933231240Sken desc_ioc_state = "success"; 1934231240Sken break; 1935231240Sken case MPI2_IOCSTATUS_INVALID_FUNCTION: 1936231240Sken desc_ioc_state = "invalid function"; 1937231240Sken break; 1938231240Sken case MPI2_IOCSTATUS_SCSI_RECOVERED_ERROR: 1939231240Sken desc_ioc_state = "scsi recovered error"; 1940231240Sken break; 1941231240Sken case MPI2_IOCSTATUS_SCSI_INVALID_DEVHANDLE: 1942231240Sken desc_ioc_state = "scsi invalid dev handle"; 1943231240Sken break; 1944231240Sken case MPI2_IOCSTATUS_SCSI_DEVICE_NOT_THERE: 1945231240Sken desc_ioc_state = "scsi device not there"; 1946231240Sken break; 1947231240Sken case MPI2_IOCSTATUS_SCSI_DATA_OVERRUN: 1948231240Sken desc_ioc_state = "scsi data overrun"; 1949231240Sken break; 1950231240Sken case MPI2_IOCSTATUS_SCSI_DATA_UNDERRUN: 1951231240Sken desc_ioc_state = "scsi data underrun"; 1952231240Sken break; 1953231240Sken case MPI2_IOCSTATUS_SCSI_IO_DATA_ERROR: 1954231240Sken desc_ioc_state = "scsi io data error"; 1955231240Sken break; 1956231240Sken case MPI2_IOCSTATUS_SCSI_PROTOCOL_ERROR: 1957231240Sken desc_ioc_state = "scsi protocol error"; 1958231240Sken break; 1959231240Sken case MPI2_IOCSTATUS_SCSI_TASK_TERMINATED: 1960231240Sken desc_ioc_state = "scsi task terminated"; 1961231240Sken break; 1962231240Sken case MPI2_IOCSTATUS_SCSI_RESIDUAL_MISMATCH: 1963231240Sken desc_ioc_state = "scsi residual mismatch"; 1964231240Sken break; 1965231240Sken case MPI2_IOCSTATUS_SCSI_TASK_MGMT_FAILED: 1966231240Sken desc_ioc_state = "scsi task mgmt failed"; 1967231240Sken break; 1968231240Sken case MPI2_IOCSTATUS_SCSI_IOC_TERMINATED: 1969231240Sken desc_ioc_state = "scsi ioc terminated"; 1970231240Sken break; 1971231240Sken case MPI2_IOCSTATUS_SCSI_EXT_TERMINATED: 1972231240Sken desc_ioc_state = "scsi ext terminated"; 1973231240Sken break; 1974231240Sken case MPI2_IOCSTATUS_EEDP_GUARD_ERROR: 1975231240Sken desc_ioc_state = "eedp guard error"; 1976231240Sken break; 1977231240Sken case MPI2_IOCSTATUS_EEDP_REF_TAG_ERROR: 1978231240Sken desc_ioc_state = "eedp ref tag error"; 1979231240Sken break; 1980231240Sken case MPI2_IOCSTATUS_EEDP_APP_TAG_ERROR: 1981231240Sken desc_ioc_state = "eedp app tag error"; 1982231240Sken break; 1983231240Sken default: 1984231240Sken desc_ioc_state = "unknown"; 1985231240Sken break; 1986231240Sken } 1987231240Sken 1988231240Sken switch (scsi_status) { 1989231240Sken case MPI2_SCSI_STATUS_GOOD: 1990231240Sken desc_scsi_status = "good"; 1991231240Sken break; 1992231240Sken case MPI2_SCSI_STATUS_CHECK_CONDITION: 1993231240Sken desc_scsi_status = "check condition"; 1994231240Sken break; 1995231240Sken case MPI2_SCSI_STATUS_CONDITION_MET: 1996231240Sken desc_scsi_status = "condition met"; 1997231240Sken break; 1998231240Sken case MPI2_SCSI_STATUS_BUSY: 1999231240Sken desc_scsi_status = "busy"; 2000231240Sken break; 2001231240Sken case MPI2_SCSI_STATUS_INTERMEDIATE: 2002231240Sken desc_scsi_status = "intermediate"; 2003231240Sken break; 2004231240Sken case MPI2_SCSI_STATUS_INTERMEDIATE_CONDMET: 2005231240Sken desc_scsi_status = "intermediate condmet"; 2006231240Sken break; 2007231240Sken case MPI2_SCSI_STATUS_RESERVATION_CONFLICT: 2008231240Sken desc_scsi_status = "reservation conflict"; 2009231240Sken break; 2010231240Sken case MPI2_SCSI_STATUS_COMMAND_TERMINATED: 2011231240Sken desc_scsi_status = "command terminated"; 2012231240Sken break; 2013231240Sken case MPI2_SCSI_STATUS_TASK_SET_FULL: 2014231240Sken desc_scsi_status = "task set full"; 2015231240Sken break; 2016231240Sken case MPI2_SCSI_STATUS_ACA_ACTIVE: 2017231240Sken desc_scsi_status = "aca active"; 2018231240Sken break; 2019231240Sken case MPI2_SCSI_STATUS_TASK_ABORTED: 2020231240Sken desc_scsi_status = "task aborted"; 2021231240Sken break; 2022231240Sken default: 2023231240Sken desc_scsi_status = "unknown"; 2024231240Sken break; 2025231240Sken } 2026231240Sken 2027231240Sken desc_scsi_state[0] = '\0'; 2028231240Sken if (!scsi_state) 2029231240Sken desc_scsi_state = " "; 2030231240Sken if (scsi_state & MPI2_SCSI_STATE_RESPONSE_INFO_VALID) 2031231240Sken strcat(desc_scsi_state, "response info "); 2032231240Sken if (scsi_state & MPI2_SCSI_STATE_TERMINATED) 2033231240Sken strcat(desc_scsi_state, "state terminated "); 2034231240Sken if (scsi_state & MPI2_SCSI_STATE_NO_SCSI_STATUS) 2035231240Sken strcat(desc_scsi_state, "no status "); 2036231240Sken if (scsi_state & MPI2_SCSI_STATE_AUTOSENSE_FAILED) 2037231240Sken strcat(desc_scsi_state, "autosense failed "); 2038231240Sken if (scsi_state & MPI2_SCSI_STATE_AUTOSENSE_VALID) 2039231240Sken strcat(desc_scsi_state, "autosense valid "); 2040231240Sken 2041253460Sscottl mps_dprint(sc, MPS_XINFO, "\thandle(0x%04x), ioc_status(%s)(0x%04x)\n", 2042253460Sscottl le16toh(mpi_reply->DevHandle), desc_ioc_state, ioc_status); 2043231240Sken /* We can add more detail about underflow data here 2044231240Sken * TO-DO 2045231240Sken * */ 2046253460Sscottl mps_dprint(sc, MPS_XINFO, "\tscsi_status(%s)(0x%02x), " 2047253550Sken "scsi_state(%s)(0x%02x)\n", desc_scsi_status, scsi_status, 2048253550Sken desc_scsi_state, scsi_state); 2049231240Sken 2050253460Sscottl if (sc->mps_debug & MPS_XINFO && 2051231240Sken scsi_state & MPI2_SCSI_STATE_AUTOSENSE_VALID) { 2052253460Sscottl mps_dprint(sc, MPS_XINFO, "-> Sense Buffer Data : Start :\n"); 2053231240Sken scsi_sense_print(csio); 2054253460Sscottl mps_dprint(sc, MPS_XINFO, "-> Sense Buffer Data : End :\n"); 2055231240Sken } 2056231240Sken 2057231240Sken if (scsi_state & MPI2_SCSI_STATE_RESPONSE_INFO_VALID) { 2058231240Sken response_info = le32toh(mpi_reply->ResponseInfo); 2059231240Sken response_bytes = (u8 *)&response_info; 2060231240Sken mps_response_code(sc,response_bytes[0]); 2061231240Sken } 2062231240Sken} 2063231240Sken 2064231240Skenstatic void 2065212420Skenmpssas_scsiio_complete(struct mps_softc *sc, struct mps_command *cm) 2066212420Sken{ 2067212420Sken MPI2_SCSI_IO_REPLY *rep; 2068212420Sken union ccb *ccb; 2069230592Sken struct ccb_scsiio *csio; 2070212420Sken struct mpssas_softc *sassc; 2071230592Sken struct scsi_vpd_supported_page_list *vpd_list = NULL; 2072230592Sken u8 *TLR_bits, TLR_on; 2073230592Sken int dir = 0, i; 2074230592Sken u16 alloc_len; 2075212420Sken 2076253460Sscottl MPS_FUNCTRACE(sc); 2077230592Sken mps_dprint(sc, MPS_TRACE, 2078253460Sscottl "cm %p SMID %u ccb %p reply %p outstanding %u\n", cm, 2079253460Sscottl cm->cm_desc.Default.SMID, cm->cm_ccb, cm->cm_reply, 2080230592Sken cm->cm_targ->outstanding); 2081212420Sken 2082212420Sken callout_stop(&cm->cm_callout); 2083230592Sken mtx_assert(&sc->mps_mtx, MA_OWNED); 2084212420Sken 2085212420Sken sassc = sc->sassc; 2086212420Sken ccb = cm->cm_complete_data; 2087230592Sken csio = &ccb->csio; 2088212420Sken rep = (MPI2_SCSI_IO_REPLY *)cm->cm_reply; 2089218812Sken /* 2090218812Sken * XXX KDM if the chain allocation fails, does it matter if we do 2091218812Sken * the sync and unload here? It is simpler to do it in every case, 2092218812Sken * assuming it doesn't cause problems. 2093218812Sken */ 2094212420Sken if (cm->cm_data != NULL) { 2095212420Sken if (cm->cm_flags & MPS_CM_FLAGS_DATAIN) 2096212420Sken dir = BUS_DMASYNC_POSTREAD; 2097212420Sken else if (cm->cm_flags & MPS_CM_FLAGS_DATAOUT) 2098241844Seadler dir = BUS_DMASYNC_POSTWRITE; 2099212420Sken bus_dmamap_sync(sc->buffer_dmat, cm->cm_dmamap, dir); 2100212420Sken bus_dmamap_unload(sc->buffer_dmat, cm->cm_dmamap); 2101212420Sken } 2102212420Sken 2103230592Sken cm->cm_targ->completed++; 2104230592Sken cm->cm_targ->outstanding--; 2105230592Sken TAILQ_REMOVE(&cm->cm_targ->commands, cm, cm_link); 2106254615Sken ccb->ccb_h.status &= ~(CAM_STATUS_MASK | CAM_SIM_QUEUED); 2107230592Sken 2108230592Sken if (cm->cm_state == MPS_CM_STATE_TIMEDOUT) { 2109230592Sken TAILQ_REMOVE(&cm->cm_targ->timedout_commands, cm, cm_recovery); 2110230592Sken if (cm->cm_reply != NULL) 2111253460Sscottl mpssas_log_command(cm, MPS_RECOVERY, 2112230592Sken "completed timedout cm %p ccb %p during recovery " 2113230592Sken "ioc %x scsi %x state %x xfer %u\n", 2114230592Sken cm, cm->cm_ccb, 2115237683Sken le16toh(rep->IOCStatus), rep->SCSIStatus, rep->SCSIState, 2116237683Sken le32toh(rep->TransferCount)); 2117230592Sken else 2118253460Sscottl mpssas_log_command(cm, MPS_RECOVERY, 2119230592Sken "completed timedout cm %p ccb %p during recovery\n", 2120230592Sken cm, cm->cm_ccb); 2121230592Sken } else if (cm->cm_targ->tm != NULL) { 2122230592Sken if (cm->cm_reply != NULL) 2123253460Sscottl mpssas_log_command(cm, MPS_RECOVERY, 2124230592Sken "completed cm %p ccb %p during recovery " 2125230592Sken "ioc %x scsi %x state %x xfer %u\n", 2126230592Sken cm, cm->cm_ccb, 2127237683Sken le16toh(rep->IOCStatus), rep->SCSIStatus, rep->SCSIState, 2128237683Sken le32toh(rep->TransferCount)); 2129230592Sken else 2130253460Sscottl mpssas_log_command(cm, MPS_RECOVERY, 2131230592Sken "completed cm %p ccb %p during recovery\n", 2132230592Sken cm, cm->cm_ccb); 2133230592Sken } else if ((sc->mps_flags & MPS_FLAGS_DIAGRESET) != 0) { 2134253460Sscottl mpssas_log_command(cm, MPS_RECOVERY, 2135230592Sken "reset completed cm %p ccb %p\n", 2136230592Sken cm, cm->cm_ccb); 2137230592Sken } 2138230592Sken 2139218812Sken if ((cm->cm_flags & MPS_CM_FLAGS_ERROR_MASK) != 0) { 2140218812Sken /* 2141218812Sken * We ran into an error after we tried to map the command, 2142218812Sken * so we're getting a callback without queueing the command 2143218812Sken * to the hardware. So we set the status here, and it will 2144218812Sken * be retained below. We'll go through the "fast path", 2145218812Sken * because there can be no reply when we haven't actually 2146218812Sken * gone out to the hardware. 2147218812Sken */ 2148254615Sken ccb->ccb_h.status = CAM_REQUEUE_REQ; 2149218812Sken 2150218812Sken /* 2151218812Sken * Currently the only error included in the mask is 2152218812Sken * MPS_CM_FLAGS_CHAIN_FAILED, which means we're out of 2153218812Sken * chain frames. We need to freeze the queue until we get 2154218812Sken * a command that completed without this error, which will 2155218812Sken * hopefully have some chain frames attached that we can 2156218812Sken * use. If we wanted to get smarter about it, we would 2157218812Sken * only unfreeze the queue in this condition when we're 2158218812Sken * sure that we're getting some chain frames back. That's 2159218812Sken * probably unnecessary. 2160218812Sken */ 2161218812Sken if ((sassc->flags & MPSSAS_QUEUE_FROZEN) == 0) { 2162218812Sken xpt_freeze_simq(sassc->sim, 1); 2163218812Sken sassc->flags |= MPSSAS_QUEUE_FROZEN; 2164253460Sscottl mps_dprint(sc, MPS_XINFO, "Error sending command, " 2165219036Sken "freezing SIM queue\n"); 2166218812Sken } 2167212420Sken } 2168212420Sken 2169212420Sken /* Take the fast path to completion */ 2170212420Sken if (cm->cm_reply == NULL) { 2171218811Sken if ((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_INPROG) { 2172230592Sken if ((sc->mps_flags & MPS_FLAGS_DIAGRESET) != 0) 2173230592Sken ccb->ccb_h.status = CAM_SCSI_BUS_RESET; 2174230592Sken else { 2175230592Sken ccb->ccb_h.status = CAM_REQ_CMP; 2176230592Sken ccb->csio.scsi_status = SCSI_STATUS_OK; 2177230592Sken } 2178218812Sken if (sassc->flags & MPSSAS_QUEUE_FROZEN) { 2179218812Sken ccb->ccb_h.status |= CAM_RELEASE_SIMQ; 2180218812Sken sassc->flags &= ~MPSSAS_QUEUE_FROZEN; 2181253460Sscottl mps_dprint(sc, MPS_XINFO, 2182253550Sken "Unfreezing SIM queue\n"); 2183218812Sken } 2184230592Sken } 2185230592Sken 2186230592Sken /* 2187230592Sken * There are two scenarios where the status won't be 2188230592Sken * CAM_REQ_CMP. The first is if MPS_CM_FLAGS_ERROR_MASK is 2189230592Sken * set, the second is in the MPS_FLAGS_DIAGRESET above. 2190230592Sken */ 2191230592Sken if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) { 2192230592Sken /* 2193230592Sken * Freeze the dev queue so that commands are 2194230592Sken * executed in the correct order with after error 2195230592Sken * recovery. 2196230592Sken */ 2197218812Sken ccb->ccb_h.status |= CAM_DEV_QFRZN; 2198218812Sken xpt_freeze_devq(ccb->ccb_h.path, /*count*/ 1); 2199218811Sken } 2200212420Sken mps_free_command(sc, cm); 2201212420Sken xpt_done(ccb); 2202212420Sken return; 2203212420Sken } 2204212420Sken 2205253460Sscottl mpssas_log_command(cm, MPS_XINFO, 2206253460Sscottl "ioc %x scsi %x state %x xfer %u\n", 2207253460Sscottl le16toh(rep->IOCStatus), rep->SCSIStatus, rep->SCSIState, 2208253460Sscottl le32toh(rep->TransferCount)); 2209212420Sken 2210230592Sken /* 2211230592Sken * If this is a Direct Drive I/O, reissue the I/O to the original IR 2212230592Sken * Volume if an error occurred (normal I/O retry). Use the original 2213230592Sken * CCB, but set a flag that this will be a retry so that it's sent to 2214230592Sken * the original volume. Free the command but reuse the CCB. 2215230592Sken */ 2216230592Sken if (cm->cm_flags & MPS_CM_FLAGS_DD_IO) { 2217230592Sken mps_free_command(sc, cm); 2218230592Sken ccb->ccb_h.status = MPS_WD_RETRY; 2219230592Sken mpssas_action_scsiio(sassc, ccb); 2220230592Sken return; 2221230592Sken } 2222230592Sken 2223237683Sken switch (le16toh(rep->IOCStatus) & MPI2_IOCSTATUS_MASK) { 2224212420Sken case MPI2_IOCSTATUS_SCSI_DATA_UNDERRUN: 2225237683Sken csio->resid = cm->cm_length - le32toh(rep->TransferCount); 2226212420Sken /* FALLTHROUGH */ 2227212420Sken case MPI2_IOCSTATUS_SUCCESS: 2228212420Sken case MPI2_IOCSTATUS_SCSI_RECOVERED_ERROR: 2229230592Sken 2230237683Sken if ((le16toh(rep->IOCStatus) & MPI2_IOCSTATUS_MASK) == 2231230592Sken MPI2_IOCSTATUS_SCSI_RECOVERED_ERROR) 2232253460Sscottl mpssas_log_command(cm, MPS_XINFO, "recovered error\n"); 2233230592Sken 2234230592Sken /* Completion failed at the transport level. */ 2235230592Sken if (rep->SCSIState & (MPI2_SCSI_STATE_NO_SCSI_STATUS | 2236230592Sken MPI2_SCSI_STATE_TERMINATED)) { 2237230592Sken ccb->ccb_h.status = CAM_REQ_CMP_ERR; 2238230592Sken break; 2239230592Sken } 2240230592Sken 2241230592Sken /* In a modern packetized environment, an autosense failure 2242230592Sken * implies that there's not much else that can be done to 2243230592Sken * recover the command. 2244230592Sken */ 2245230592Sken if (rep->SCSIState & MPI2_SCSI_STATE_AUTOSENSE_FAILED) { 2246230592Sken ccb->ccb_h.status = CAM_AUTOSENSE_FAIL; 2247230592Sken break; 2248230592Sken } 2249230592Sken 2250230592Sken /* 2251230592Sken * CAM doesn't care about SAS Response Info data, but if this is 2252230592Sken * the state check if TLR should be done. If not, clear the 2253230592Sken * TLR_bits for the target. 2254230592Sken */ 2255230592Sken if ((rep->SCSIState & MPI2_SCSI_STATE_RESPONSE_INFO_VALID) && 2256237683Sken ((le32toh(rep->ResponseInfo) & MPI2_SCSI_RI_MASK_REASONCODE) == 2257230592Sken MPS_SCSI_RI_INVALID_FRAME)) { 2258230592Sken sc->mapping_table[csio->ccb_h.target_id].TLR_bits = 2259230592Sken (u8)MPI2_SCSIIO_CONTROL_NO_TLR; 2260230592Sken } 2261230592Sken 2262230592Sken /* 2263230592Sken * Intentionally override the normal SCSI status reporting 2264230592Sken * for these two cases. These are likely to happen in a 2265230592Sken * multi-initiator environment, and we want to make sure that 2266230592Sken * CAM retries these commands rather than fail them. 2267230592Sken */ 2268230592Sken if ((rep->SCSIStatus == MPI2_SCSI_STATUS_COMMAND_TERMINATED) || 2269230592Sken (rep->SCSIStatus == MPI2_SCSI_STATUS_TASK_ABORTED)) { 2270230592Sken ccb->ccb_h.status = CAM_REQ_ABORTED; 2271230592Sken break; 2272230592Sken } 2273230592Sken 2274230592Sken /* Handle normal status and sense */ 2275230592Sken csio->scsi_status = rep->SCSIStatus; 2276230592Sken if (rep->SCSIStatus == MPI2_SCSI_STATUS_GOOD) 2277230592Sken ccb->ccb_h.status = CAM_REQ_CMP; 2278230592Sken else 2279230592Sken ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR; 2280230592Sken 2281230592Sken if (rep->SCSIState & MPI2_SCSI_STATE_AUTOSENSE_VALID) { 2282230592Sken int sense_len, returned_sense_len; 2283230592Sken 2284237683Sken returned_sense_len = min(le32toh(rep->SenseCount), 2285230592Sken sizeof(struct scsi_sense_data)); 2286230592Sken if (returned_sense_len < ccb->csio.sense_len) 2287230592Sken ccb->csio.sense_resid = ccb->csio.sense_len - 2288230592Sken returned_sense_len; 2289230592Sken else 2290230592Sken ccb->csio.sense_resid = 0; 2291230592Sken 2292230592Sken sense_len = min(returned_sense_len, 2293230592Sken ccb->csio.sense_len - ccb->csio.sense_resid); 2294230592Sken bzero(&ccb->csio.sense_data, 2295237546Skevlo sizeof(ccb->csio.sense_data)); 2296230592Sken bcopy(cm->cm_sense, &ccb->csio.sense_data, sense_len); 2297230592Sken ccb->ccb_h.status |= CAM_AUTOSNS_VALID; 2298230592Sken } 2299230592Sken 2300230592Sken /* 2301230592Sken * Check if this is an INQUIRY command. If it's a VPD inquiry, 2302230592Sken * and it's page code 0 (Supported Page List), and there is 2303230592Sken * inquiry data, and this is for a sequential access device, and 2304230592Sken * the device is an SSP target, and TLR is supported by the 2305230592Sken * controller, turn the TLR_bits value ON if page 0x90 is 2306230592Sken * supported. 2307230592Sken */ 2308230592Sken if ((csio->cdb_io.cdb_bytes[0] == INQUIRY) && 2309230592Sken (csio->cdb_io.cdb_bytes[1] & SI_EVPD) && 2310230592Sken (csio->cdb_io.cdb_bytes[2] == SVPD_SUPPORTED_PAGE_LIST) && 2311248825Smav ((csio->ccb_h.flags & CAM_DATA_MASK) == CAM_DATA_VADDR) && 2312230592Sken (csio->data_ptr != NULL) && (((uint8_t *)cm->cm_data)[0] == 2313230592Sken T_SEQUENTIAL) && (sc->control_TLR) && 2314230592Sken (sc->mapping_table[csio->ccb_h.target_id].device_info & 2315230592Sken MPI2_SAS_DEVICE_INFO_SSP_TARGET)) { 2316230592Sken vpd_list = (struct scsi_vpd_supported_page_list *) 2317230592Sken csio->data_ptr; 2318230592Sken TLR_bits = &sc->mapping_table[csio->ccb_h.target_id]. 2319230592Sken TLR_bits; 2320230592Sken *TLR_bits = (u8)MPI2_SCSIIO_CONTROL_NO_TLR; 2321230592Sken TLR_on = (u8)MPI2_SCSIIO_CONTROL_TLR_ON; 2322230592Sken alloc_len = ((u16)csio->cdb_io.cdb_bytes[3] << 8) + 2323230592Sken csio->cdb_io.cdb_bytes[4]; 2324230592Sken for (i = 0; i < MIN(vpd_list->length, alloc_len); i++) { 2325230592Sken if (vpd_list->list[i] == 0x90) { 2326230592Sken *TLR_bits = TLR_on; 2327230592Sken break; 2328230592Sken } 2329230592Sken } 2330230592Sken } 2331212420Sken break; 2332212420Sken case MPI2_IOCSTATUS_SCSI_INVALID_DEVHANDLE: 2333212420Sken case MPI2_IOCSTATUS_SCSI_DEVICE_NOT_THERE: 2334230592Sken /* 2335230592Sken * If devinfo is 0 this will be a volume. In that case don't 2336230592Sken * tell CAM that the volume is not there. We want volumes to 2337230592Sken * be enumerated until they are deleted/removed, not just 2338230592Sken * failed. 2339230592Sken */ 2340230592Sken if (cm->cm_targ->devinfo == 0) 2341230592Sken ccb->ccb_h.status = CAM_REQ_CMP; 2342230592Sken else 2343230592Sken ccb->ccb_h.status = CAM_DEV_NOT_THERE; 2344212420Sken break; 2345230592Sken case MPI2_IOCSTATUS_INVALID_SGL: 2346230592Sken mps_print_scsiio_cmd(sc, cm); 2347230592Sken ccb->ccb_h.status = CAM_UNREC_HBA_ERROR; 2348230592Sken break; 2349212420Sken case MPI2_IOCSTATUS_SCSI_TASK_TERMINATED: 2350212420Sken /* 2351212420Sken * This is one of the responses that comes back when an I/O 2352212420Sken * has been aborted. If it is because of a timeout that we 2353212420Sken * initiated, just set the status to CAM_CMD_TIMEOUT. 2354212420Sken * Otherwise set it to CAM_REQ_ABORTED. The effect on the 2355212420Sken * command is the same (it gets retried, subject to the 2356212420Sken * retry counter), the only difference is what gets printed 2357212420Sken * on the console. 2358212420Sken */ 2359212420Sken if (cm->cm_state == MPS_CM_STATE_TIMEDOUT) 2360212420Sken ccb->ccb_h.status = CAM_CMD_TIMEOUT; 2361212420Sken else 2362212420Sken ccb->ccb_h.status = CAM_REQ_ABORTED; 2363212420Sken break; 2364230592Sken case MPI2_IOCSTATUS_SCSI_DATA_OVERRUN: 2365230592Sken /* resid is ignored for this condition */ 2366230592Sken csio->resid = 0; 2367230592Sken ccb->ccb_h.status = CAM_DATA_RUN_ERR; 2368230592Sken break; 2369212420Sken case MPI2_IOCSTATUS_SCSI_IOC_TERMINATED: 2370212420Sken case MPI2_IOCSTATUS_SCSI_EXT_TERMINATED: 2371230592Sken /* 2372230592Sken * Since these are generally external (i.e. hopefully 2373230592Sken * transient transport-related) errors, retry these without 2374230592Sken * decrementing the retry count. 2375230592Sken */ 2376218812Sken ccb->ccb_h.status = CAM_REQUEUE_REQ; 2377253460Sscottl mpssas_log_command(cm, MPS_INFO, 2378230592Sken "terminated ioc %x scsi %x state %x xfer %u\n", 2379253460Sscottl le16toh(rep->IOCStatus), rep->SCSIStatus, rep->SCSIState, 2380253460Sscottl le32toh(rep->TransferCount)); 2381212420Sken break; 2382212420Sken case MPI2_IOCSTATUS_INVALID_FUNCTION: 2383212420Sken case MPI2_IOCSTATUS_INTERNAL_ERROR: 2384212420Sken case MPI2_IOCSTATUS_INVALID_VPID: 2385212420Sken case MPI2_IOCSTATUS_INVALID_FIELD: 2386212420Sken case MPI2_IOCSTATUS_INVALID_STATE: 2387212420Sken case MPI2_IOCSTATUS_OP_STATE_NOT_SUPPORTED: 2388212420Sken case MPI2_IOCSTATUS_SCSI_IO_DATA_ERROR: 2389212420Sken case MPI2_IOCSTATUS_SCSI_PROTOCOL_ERROR: 2390212420Sken case MPI2_IOCSTATUS_SCSI_RESIDUAL_MISMATCH: 2391212420Sken case MPI2_IOCSTATUS_SCSI_TASK_MGMT_FAILED: 2392212420Sken default: 2393253460Sscottl mpssas_log_command(cm, MPS_XINFO, 2394230592Sken "completed ioc %x scsi %x state %x xfer %u\n", 2395253460Sscottl le16toh(rep->IOCStatus), rep->SCSIStatus, rep->SCSIState, 2396253460Sscottl le32toh(rep->TransferCount)); 2397230592Sken csio->resid = cm->cm_length; 2398212420Sken ccb->ccb_h.status = CAM_REQ_CMP_ERR; 2399230592Sken break; 2400212420Sken } 2401231240Sken 2402231240Sken mps_sc_failed_io_info(sc,csio,rep); 2403212420Sken 2404230592Sken if (sassc->flags & MPSSAS_QUEUE_FROZEN) { 2405230592Sken ccb->ccb_h.status |= CAM_RELEASE_SIMQ; 2406230592Sken sassc->flags &= ~MPSSAS_QUEUE_FROZEN; 2407253460Sscottl mps_dprint(sc, MPS_XINFO, "Command completed, " 2408253550Sken "unfreezing SIM queue\n"); 2409230592Sken } 2410212420Sken 2411230592Sken if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) { 2412230592Sken ccb->ccb_h.status |= CAM_DEV_QFRZN; 2413230592Sken xpt_freeze_devq(ccb->ccb_h.path, /*count*/ 1); 2414230592Sken } 2415212420Sken 2416230592Sken mps_free_command(sc, cm); 2417230592Sken xpt_done(ccb); 2418230592Sken} 2419230592Sken 2420237683Sken/* All Request reached here are Endian safe */ 2421230592Skenstatic void 2422230592Skenmpssas_direct_drive_io(struct mpssas_softc *sassc, struct mps_command *cm, 2423230592Sken union ccb *ccb) { 2424230592Sken pMpi2SCSIIORequest_t pIO_req; 2425230592Sken struct mps_softc *sc = sassc->sc; 2426230592Sken uint64_t virtLBA; 2427230592Sken uint32_t physLBA, stripe_offset, stripe_unit; 2428230592Sken uint32_t io_size, column; 2429230592Sken uint8_t *ptrLBA, lba_idx, physLBA_byte, *CDB; 2430230592Sken 2431230592Sken /* 2432230592Sken * If this is a valid SCSI command (Read6, Read10, Read16, Write6, 2433230592Sken * Write10, or Write16), build a direct I/O message. Otherwise, the I/O 2434230592Sken * will be sent to the IR volume itself. Since Read6 and Write6 are a 2435230592Sken * bit different than the 10/16 CDBs, handle them separately. 2436230592Sken */ 2437230592Sken pIO_req = (pMpi2SCSIIORequest_t)cm->cm_req; 2438230592Sken CDB = pIO_req->CDB.CDB32; 2439230592Sken 2440230592Sken /* 2441230592Sken * Handle 6 byte CDBs. 2442230592Sken */ 2443230592Sken if ((pIO_req->DevHandle == sc->DD_dev_handle) && ((CDB[0] == READ_6) || 2444230592Sken (CDB[0] == WRITE_6))) { 2445230592Sken /* 2446230592Sken * Get the transfer size in blocks. 2447230592Sken */ 2448230592Sken io_size = (cm->cm_length >> sc->DD_block_exponent); 2449230592Sken 2450230592Sken /* 2451230592Sken * Get virtual LBA given in the CDB. 2452230592Sken */ 2453230592Sken virtLBA = ((uint64_t)(CDB[1] & 0x1F) << 16) | 2454230592Sken ((uint64_t)CDB[2] << 8) | (uint64_t)CDB[3]; 2455230592Sken 2456230592Sken /* 2457230592Sken * Check that LBA range for I/O does not exceed volume's 2458230592Sken * MaxLBA. 2459230592Sken */ 2460230592Sken if ((virtLBA + (uint64_t)io_size - 1) <= 2461230592Sken sc->DD_max_lba) { 2462230592Sken /* 2463230592Sken * Check if the I/O crosses a stripe boundary. If not, 2464230592Sken * translate the virtual LBA to a physical LBA and set 2465230592Sken * the DevHandle for the PhysDisk to be used. If it 2466230592Sken * does cross a boundry, do normal I/O. To get the 2467230592Sken * right DevHandle to use, get the map number for the 2468230592Sken * column, then use that map number to look up the 2469230592Sken * DevHandle of the PhysDisk. 2470230592Sken */ 2471230592Sken stripe_offset = (uint32_t)virtLBA & 2472230592Sken (sc->DD_stripe_size - 1); 2473230592Sken if ((stripe_offset + io_size) <= sc->DD_stripe_size) { 2474230592Sken physLBA = (uint32_t)virtLBA >> 2475230592Sken sc->DD_stripe_exponent; 2476230592Sken stripe_unit = physLBA / sc->DD_num_phys_disks; 2477230592Sken column = physLBA % sc->DD_num_phys_disks; 2478230592Sken pIO_req->DevHandle = 2479237683Sken htole16(sc->DD_column_map[column].dev_handle); 2480237683Sken /* ???? Is this endian safe*/ 2481230592Sken cm->cm_desc.SCSIIO.DevHandle = 2482230592Sken pIO_req->DevHandle; 2483230592Sken 2484230592Sken physLBA = (stripe_unit << 2485230592Sken sc->DD_stripe_exponent) + stripe_offset; 2486230592Sken ptrLBA = &pIO_req->CDB.CDB32[1]; 2487230592Sken physLBA_byte = (uint8_t)(physLBA >> 16); 2488230592Sken *ptrLBA = physLBA_byte; 2489230592Sken ptrLBA = &pIO_req->CDB.CDB32[2]; 2490230592Sken physLBA_byte = (uint8_t)(physLBA >> 8); 2491230592Sken *ptrLBA = physLBA_byte; 2492230592Sken ptrLBA = &pIO_req->CDB.CDB32[3]; 2493230592Sken physLBA_byte = (uint8_t)physLBA; 2494230592Sken *ptrLBA = physLBA_byte; 2495230592Sken 2496230592Sken /* 2497230592Sken * Set flag that Direct Drive I/O is 2498230592Sken * being done. 2499230592Sken */ 2500230592Sken cm->cm_flags |= MPS_CM_FLAGS_DD_IO; 2501230592Sken } 2502212420Sken } 2503230592Sken return; 2504212420Sken } 2505212420Sken 2506230592Sken /* 2507237683Sken * Handle 10, 12 or 16 byte CDBs. 2508230592Sken */ 2509230592Sken if ((pIO_req->DevHandle == sc->DD_dev_handle) && ((CDB[0] == READ_10) || 2510230592Sken (CDB[0] == WRITE_10) || (CDB[0] == READ_16) || 2511237683Sken (CDB[0] == WRITE_16) || (CDB[0] == READ_12) || 2512237683Sken (CDB[0] == WRITE_12))) { 2513230592Sken /* 2514230592Sken * For 16-byte CDB's, verify that the upper 4 bytes of the CDB 2515230592Sken * are 0. If not, this is accessing beyond 2TB so handle it in 2516237683Sken * the else section. 10-byte and 12-byte CDB's are OK. 2517237683Sken * FreeBSD sends very rare 12 byte READ/WRITE, but driver is 2518237683Sken * ready to accept 12byte CDB for Direct IOs. 2519230592Sken */ 2520237683Sken if ((CDB[0] == READ_10 || CDB[0] == WRITE_10) || 2521237683Sken (CDB[0] == READ_12 || CDB[0] == WRITE_12) || 2522230592Sken !(CDB[2] | CDB[3] | CDB[4] | CDB[5])) { 2523230592Sken /* 2524230592Sken * Get the transfer size in blocks. 2525230592Sken */ 2526230592Sken io_size = (cm->cm_length >> sc->DD_block_exponent); 2527225950Sken 2528230592Sken /* 2529230592Sken * Get virtual LBA. Point to correct lower 4 bytes of 2530230592Sken * LBA in the CDB depending on command. 2531230592Sken */ 2532237683Sken lba_idx = ((CDB[0] == READ_12) || 2533237683Sken (CDB[0] == WRITE_12) || 2534237683Sken (CDB[0] == READ_10) || 2535237683Sken (CDB[0] == WRITE_10))? 2 : 6; 2536230592Sken virtLBA = ((uint64_t)CDB[lba_idx] << 24) | 2537230592Sken ((uint64_t)CDB[lba_idx + 1] << 16) | 2538230592Sken ((uint64_t)CDB[lba_idx + 2] << 8) | 2539230592Sken (uint64_t)CDB[lba_idx + 3]; 2540225950Sken 2541230592Sken /* 2542230592Sken * Check that LBA range for I/O does not exceed volume's 2543230592Sken * MaxLBA. 2544230592Sken */ 2545230592Sken if ((virtLBA + (uint64_t)io_size - 1) <= 2546230592Sken sc->DD_max_lba) { 2547230592Sken /* 2548230592Sken * Check if the I/O crosses a stripe boundary. 2549230592Sken * If not, translate the virtual LBA to a 2550230592Sken * physical LBA and set the DevHandle for the 2551230592Sken * PhysDisk to be used. If it does cross a 2552230592Sken * boundry, do normal I/O. To get the right 2553230592Sken * DevHandle to use, get the map number for the 2554230592Sken * column, then use that map number to look up 2555230592Sken * the DevHandle of the PhysDisk. 2556230592Sken */ 2557230592Sken stripe_offset = (uint32_t)virtLBA & 2558230592Sken (sc->DD_stripe_size - 1); 2559230592Sken if ((stripe_offset + io_size) <= 2560230592Sken sc->DD_stripe_size) { 2561230592Sken physLBA = (uint32_t)virtLBA >> 2562230592Sken sc->DD_stripe_exponent; 2563230592Sken stripe_unit = physLBA / 2564230592Sken sc->DD_num_phys_disks; 2565230592Sken column = physLBA % 2566230592Sken sc->DD_num_phys_disks; 2567230592Sken pIO_req->DevHandle = 2568237683Sken htole16(sc->DD_column_map[column]. 2569237683Sken dev_handle); 2570230592Sken cm->cm_desc.SCSIIO.DevHandle = 2571230592Sken pIO_req->DevHandle; 2572212420Sken 2573230592Sken physLBA = (stripe_unit << 2574230592Sken sc->DD_stripe_exponent) + 2575230592Sken stripe_offset; 2576230592Sken ptrLBA = 2577230592Sken &pIO_req->CDB.CDB32[lba_idx]; 2578230592Sken physLBA_byte = (uint8_t)(physLBA >> 24); 2579230592Sken *ptrLBA = physLBA_byte; 2580230592Sken ptrLBA = 2581230592Sken &pIO_req->CDB.CDB32[lba_idx + 1]; 2582230592Sken physLBA_byte = (uint8_t)(physLBA >> 16); 2583230592Sken *ptrLBA = physLBA_byte; 2584230592Sken ptrLBA = 2585230592Sken &pIO_req->CDB.CDB32[lba_idx + 2]; 2586230592Sken physLBA_byte = (uint8_t)(physLBA >> 8); 2587230592Sken *ptrLBA = physLBA_byte; 2588230592Sken ptrLBA = 2589230592Sken &pIO_req->CDB.CDB32[lba_idx + 3]; 2590230592Sken physLBA_byte = (uint8_t)physLBA; 2591230592Sken *ptrLBA = physLBA_byte; 2592212420Sken 2593230592Sken /* 2594230592Sken * Set flag that Direct Drive I/O is 2595230592Sken * being done. 2596230592Sken */ 2597230592Sken cm->cm_flags |= MPS_CM_FLAGS_DD_IO; 2598230592Sken } 2599230592Sken } 2600230592Sken } else { 2601230592Sken /* 2602230592Sken * 16-byte CDB and the upper 4 bytes of the CDB are not 2603230592Sken * 0. Get the transfer size in blocks. 2604230592Sken */ 2605230592Sken io_size = (cm->cm_length >> sc->DD_block_exponent); 2606212420Sken 2607230592Sken /* 2608230592Sken * Get virtual LBA. 2609230592Sken */ 2610230592Sken virtLBA = ((uint64_t)CDB[2] << 54) | 2611230592Sken ((uint64_t)CDB[3] << 48) | 2612230592Sken ((uint64_t)CDB[4] << 40) | 2613230592Sken ((uint64_t)CDB[5] << 32) | 2614230592Sken ((uint64_t)CDB[6] << 24) | 2615230592Sken ((uint64_t)CDB[7] << 16) | 2616230592Sken ((uint64_t)CDB[8] << 8) | 2617230592Sken (uint64_t)CDB[9]; 2618230592Sken 2619230592Sken /* 2620230592Sken * Check that LBA range for I/O does not exceed volume's 2621230592Sken * MaxLBA. 2622230592Sken */ 2623230592Sken if ((virtLBA + (uint64_t)io_size - 1) <= 2624230592Sken sc->DD_max_lba) { 2625230592Sken /* 2626230592Sken * Check if the I/O crosses a stripe boundary. 2627230592Sken * If not, translate the virtual LBA to a 2628230592Sken * physical LBA and set the DevHandle for the 2629230592Sken * PhysDisk to be used. If it does cross a 2630230592Sken * boundry, do normal I/O. To get the right 2631230592Sken * DevHandle to use, get the map number for the 2632230592Sken * column, then use that map number to look up 2633230592Sken * the DevHandle of the PhysDisk. 2634230592Sken */ 2635230592Sken stripe_offset = (uint32_t)virtLBA & 2636230592Sken (sc->DD_stripe_size - 1); 2637230592Sken if ((stripe_offset + io_size) <= 2638230592Sken sc->DD_stripe_size) { 2639230592Sken physLBA = (uint32_t)(virtLBA >> 2640230592Sken sc->DD_stripe_exponent); 2641230592Sken stripe_unit = physLBA / 2642230592Sken sc->DD_num_phys_disks; 2643230592Sken column = physLBA % 2644230592Sken sc->DD_num_phys_disks; 2645230592Sken pIO_req->DevHandle = 2646237683Sken htole16(sc->DD_column_map[column]. 2647237683Sken dev_handle); 2648230592Sken cm->cm_desc.SCSIIO.DevHandle = 2649230592Sken pIO_req->DevHandle; 2650230592Sken 2651230592Sken physLBA = (stripe_unit << 2652230592Sken sc->DD_stripe_exponent) + 2653230592Sken stripe_offset; 2654230592Sken 2655230592Sken /* 2656230592Sken * Set upper 4 bytes of LBA to 0. We 2657230592Sken * assume that the phys disks are less 2658230592Sken * than 2 TB's in size. Then, set the 2659230592Sken * lower 4 bytes. 2660230592Sken */ 2661230592Sken pIO_req->CDB.CDB32[2] = 0; 2662230592Sken pIO_req->CDB.CDB32[3] = 0; 2663230592Sken pIO_req->CDB.CDB32[4] = 0; 2664230592Sken pIO_req->CDB.CDB32[5] = 0; 2665230592Sken ptrLBA = &pIO_req->CDB.CDB32[6]; 2666230592Sken physLBA_byte = (uint8_t)(physLBA >> 24); 2667230592Sken *ptrLBA = physLBA_byte; 2668230592Sken ptrLBA = &pIO_req->CDB.CDB32[7]; 2669230592Sken physLBA_byte = (uint8_t)(physLBA >> 16); 2670230592Sken *ptrLBA = physLBA_byte; 2671230592Sken ptrLBA = &pIO_req->CDB.CDB32[8]; 2672230592Sken physLBA_byte = (uint8_t)(physLBA >> 8); 2673230592Sken *ptrLBA = physLBA_byte; 2674230592Sken ptrLBA = &pIO_req->CDB.CDB32[9]; 2675230592Sken physLBA_byte = (uint8_t)physLBA; 2676230592Sken *ptrLBA = physLBA_byte; 2677230592Sken 2678230592Sken /* 2679230592Sken * Set flag that Direct Drive I/O is 2680230592Sken * being done. 2681230592Sken */ 2682230592Sken cm->cm_flags |= MPS_CM_FLAGS_DD_IO; 2683230592Sken } 2684230592Sken } 2685230592Sken } 2686218812Sken } 2687212420Sken} 2688212420Sken 2689216088Sken#if __FreeBSD_version >= 900026 2690212420Skenstatic void 2691216088Skenmpssas_smpio_complete(struct mps_softc *sc, struct mps_command *cm) 2692216088Sken{ 2693216088Sken MPI2_SMP_PASSTHROUGH_REPLY *rpl; 2694216088Sken MPI2_SMP_PASSTHROUGH_REQUEST *req; 2695216088Sken uint64_t sasaddr; 2696216088Sken union ccb *ccb; 2697216088Sken 2698216088Sken ccb = cm->cm_complete_data; 2699218812Sken 2700218812Sken /* 2701218812Sken * Currently there should be no way we can hit this case. It only 2702218812Sken * happens when we have a failure to allocate chain frames, and SMP 2703218812Sken * commands require two S/G elements only. That should be handled 2704218812Sken * in the standard request size. 2705218812Sken */ 2706218812Sken if ((cm->cm_flags & MPS_CM_FLAGS_ERROR_MASK) != 0) { 2707253460Sscottl mps_dprint(sc, MPS_ERROR,"%s: cm_flags = %#x on SMP request!\n", 2708218812Sken __func__, cm->cm_flags); 2709218812Sken ccb->ccb_h.status = CAM_REQ_CMP_ERR; 2710218812Sken goto bailout; 2711230592Sken } 2712218812Sken 2713216088Sken rpl = (MPI2_SMP_PASSTHROUGH_REPLY *)cm->cm_reply; 2714216088Sken if (rpl == NULL) { 2715253460Sscottl mps_dprint(sc, MPS_ERROR, "%s: NULL cm_reply!\n", __func__); 2716216088Sken ccb->ccb_h.status = CAM_REQ_CMP_ERR; 2717216088Sken goto bailout; 2718216088Sken } 2719216088Sken 2720216088Sken req = (MPI2_SMP_PASSTHROUGH_REQUEST *)cm->cm_req; 2721216088Sken sasaddr = le32toh(req->SASAddress.Low); 2722216088Sken sasaddr |= ((uint64_t)(le32toh(req->SASAddress.High))) << 32; 2723216088Sken 2724253550Sken if ((le16toh(rpl->IOCStatus) & MPI2_IOCSTATUS_MASK) != 2725253550Sken MPI2_IOCSTATUS_SUCCESS || 2726216088Sken rpl->SASStatus != MPI2_SASSTATUS_SUCCESS) { 2727253460Sscottl mps_dprint(sc, MPS_XINFO, "%s: IOCStatus %04x SASStatus %02x\n", 2728237683Sken __func__, le16toh(rpl->IOCStatus), rpl->SASStatus); 2729216088Sken ccb->ccb_h.status = CAM_REQ_CMP_ERR; 2730216088Sken goto bailout; 2731216088Sken } 2732216088Sken 2733253460Sscottl mps_dprint(sc, MPS_XINFO, "%s: SMP request to SAS address " 2734216088Sken "%#jx completed successfully\n", __func__, 2735216088Sken (uintmax_t)sasaddr); 2736216088Sken 2737216088Sken if (ccb->smpio.smp_response[2] == SMP_FR_ACCEPTED) 2738216088Sken ccb->ccb_h.status = CAM_REQ_CMP; 2739216088Sken else 2740216088Sken ccb->ccb_h.status = CAM_SMP_STATUS_ERROR; 2741216088Sken 2742216088Skenbailout: 2743216088Sken /* 2744216088Sken * We sync in both directions because we had DMAs in the S/G list 2745216088Sken * in both directions. 2746216088Sken */ 2747216088Sken bus_dmamap_sync(sc->buffer_dmat, cm->cm_dmamap, 2748216088Sken BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); 2749216088Sken bus_dmamap_unload(sc->buffer_dmat, cm->cm_dmamap); 2750216088Sken mps_free_command(sc, cm); 2751216088Sken xpt_done(ccb); 2752216088Sken} 2753216088Sken 2754216088Skenstatic void 2755216088Skenmpssas_send_smpcmd(struct mpssas_softc *sassc, union ccb *ccb, uint64_t sasaddr) 2756216088Sken{ 2757216088Sken struct mps_command *cm; 2758216088Sken uint8_t *request, *response; 2759216088Sken MPI2_SMP_PASSTHROUGH_REQUEST *req; 2760216088Sken struct mps_softc *sc; 2761216088Sken struct sglist *sg; 2762216088Sken int error; 2763216088Sken 2764216088Sken sc = sassc->sc; 2765216088Sken sg = NULL; 2766216088Sken error = 0; 2767216088Sken 2768216088Sken /* 2769216088Sken * XXX We don't yet support physical addresses here. 2770216088Sken */ 2771246713Skib switch ((ccb->ccb_h.flags & CAM_DATA_MASK)) { 2772246713Skib case CAM_DATA_PADDR: 2773246713Skib case CAM_DATA_SG_PADDR: 2774253460Sscottl mps_dprint(sc, MPS_ERROR, 2775253460Sscottl "%s: physical addresses not supported\n", __func__); 2776216088Sken ccb->ccb_h.status = CAM_REQ_INVALID; 2777216088Sken xpt_done(ccb); 2778216088Sken return; 2779246713Skib case CAM_DATA_SG: 2780216088Sken /* 2781216088Sken * The chip does not support more than one buffer for the 2782216088Sken * request or response. 2783216088Sken */ 2784216088Sken if ((ccb->smpio.smp_request_sglist_cnt > 1) 2785216088Sken || (ccb->smpio.smp_response_sglist_cnt > 1)) { 2786253460Sscottl mps_dprint(sc, MPS_ERROR, 2787253460Sscottl "%s: multiple request or response " 2788216088Sken "buffer segments not supported for SMP\n", 2789216088Sken __func__); 2790216088Sken ccb->ccb_h.status = CAM_REQ_INVALID; 2791216088Sken xpt_done(ccb); 2792216088Sken return; 2793216088Sken } 2794216088Sken 2795216088Sken /* 2796216088Sken * The CAM_SCATTER_VALID flag was originally implemented 2797216088Sken * for the XPT_SCSI_IO CCB, which only has one data pointer. 2798216088Sken * We have two. So, just take that flag to mean that we 2799216088Sken * might have S/G lists, and look at the S/G segment count 2800216088Sken * to figure out whether that is the case for each individual 2801216088Sken * buffer. 2802216088Sken */ 2803216088Sken if (ccb->smpio.smp_request_sglist_cnt != 0) { 2804216088Sken bus_dma_segment_t *req_sg; 2805216088Sken 2806216088Sken req_sg = (bus_dma_segment_t *)ccb->smpio.smp_request; 2807241145Sken request = (uint8_t *)(uintptr_t)req_sg[0].ds_addr; 2808216088Sken } else 2809216088Sken request = ccb->smpio.smp_request; 2810216088Sken 2811216088Sken if (ccb->smpio.smp_response_sglist_cnt != 0) { 2812216088Sken bus_dma_segment_t *rsp_sg; 2813216088Sken 2814216088Sken rsp_sg = (bus_dma_segment_t *)ccb->smpio.smp_response; 2815241145Sken response = (uint8_t *)(uintptr_t)rsp_sg[0].ds_addr; 2816216088Sken } else 2817216088Sken response = ccb->smpio.smp_response; 2818246713Skib break; 2819246713Skib case CAM_DATA_VADDR: 2820216088Sken request = ccb->smpio.smp_request; 2821216088Sken response = ccb->smpio.smp_response; 2822246713Skib break; 2823246713Skib default: 2824246713Skib ccb->ccb_h.status = CAM_REQ_INVALID; 2825246713Skib xpt_done(ccb); 2826246713Skib return; 2827216088Sken } 2828216088Sken 2829216088Sken cm = mps_alloc_command(sc); 2830216088Sken if (cm == NULL) { 2831253460Sscottl mps_dprint(sc, MPS_ERROR, 2832253460Sscottl "%s: cannot allocate command\n", __func__); 2833216088Sken ccb->ccb_h.status = CAM_RESRC_UNAVAIL; 2834216088Sken xpt_done(ccb); 2835216088Sken return; 2836216088Sken } 2837216088Sken 2838216088Sken req = (MPI2_SMP_PASSTHROUGH_REQUEST *)cm->cm_req; 2839216088Sken bzero(req, sizeof(*req)); 2840216088Sken req->Function = MPI2_FUNCTION_SMP_PASSTHROUGH; 2841216088Sken 2842216088Sken /* Allow the chip to use any route to this SAS address. */ 2843216088Sken req->PhysicalPort = 0xff; 2844216088Sken 2845237683Sken req->RequestDataLength = htole16(ccb->smpio.smp_request_len); 2846216088Sken req->SGLFlags = 2847216088Sken MPI2_SGLFLAGS_SYSTEM_ADDRESS_SPACE | MPI2_SGLFLAGS_SGL_TYPE_MPI; 2848216088Sken 2849253460Sscottl mps_dprint(sc, MPS_XINFO, "%s: sending SMP request to SAS " 2850253550Sken "address %#jx\n", __func__, (uintmax_t)sasaddr); 2851216088Sken 2852216088Sken mpi_init_sge(cm, req, &req->SGL); 2853216088Sken 2854216088Sken /* 2855216088Sken * Set up a uio to pass into mps_map_command(). This allows us to 2856216088Sken * do one map command, and one busdma call in there. 2857216088Sken */ 2858216088Sken cm->cm_uio.uio_iov = cm->cm_iovec; 2859216088Sken cm->cm_uio.uio_iovcnt = 2; 2860216088Sken cm->cm_uio.uio_segflg = UIO_SYSSPACE; 2861216088Sken 2862216088Sken /* 2863216088Sken * The read/write flag isn't used by busdma, but set it just in 2864216088Sken * case. This isn't exactly accurate, either, since we're going in 2865216088Sken * both directions. 2866216088Sken */ 2867216088Sken cm->cm_uio.uio_rw = UIO_WRITE; 2868216088Sken 2869216088Sken cm->cm_iovec[0].iov_base = request; 2870237683Sken cm->cm_iovec[0].iov_len = le16toh(req->RequestDataLength); 2871216088Sken cm->cm_iovec[1].iov_base = response; 2872216088Sken cm->cm_iovec[1].iov_len = ccb->smpio.smp_response_len; 2873216088Sken 2874216088Sken cm->cm_uio.uio_resid = cm->cm_iovec[0].iov_len + 2875216088Sken cm->cm_iovec[1].iov_len; 2876216088Sken 2877216088Sken /* 2878216088Sken * Trigger a warning message in mps_data_cb() for the user if we 2879216088Sken * wind up exceeding two S/G segments. The chip expects one 2880216088Sken * segment for the request and another for the response. 2881216088Sken */ 2882216088Sken cm->cm_max_segs = 2; 2883216088Sken 2884216088Sken cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 2885216088Sken cm->cm_complete = mpssas_smpio_complete; 2886216088Sken cm->cm_complete_data = ccb; 2887216088Sken 2888216088Sken /* 2889216088Sken * Tell the mapping code that we're using a uio, and that this is 2890216088Sken * an SMP passthrough request. There is a little special-case 2891216088Sken * logic there (in mps_data_cb()) to handle the bidirectional 2892216088Sken * transfer. 2893216088Sken */ 2894216088Sken cm->cm_flags |= MPS_CM_FLAGS_USE_UIO | MPS_CM_FLAGS_SMP_PASS | 2895216088Sken MPS_CM_FLAGS_DATAIN | MPS_CM_FLAGS_DATAOUT; 2896216088Sken 2897216088Sken /* The chip data format is little endian. */ 2898216088Sken req->SASAddress.High = htole32(sasaddr >> 32); 2899216088Sken req->SASAddress.Low = htole32(sasaddr); 2900216088Sken 2901216088Sken /* 2902216088Sken * XXX Note that we don't have a timeout/abort mechanism here. 2903216088Sken * From the manual, it looks like task management requests only 2904216088Sken * work for SCSI IO and SATA passthrough requests. We may need to 2905216088Sken * have a mechanism to retry requests in the event of a chip reset 2906216088Sken * at least. Hopefully the chip will insure that any errors short 2907216088Sken * of that are relayed back to the driver. 2908216088Sken */ 2909216088Sken error = mps_map_command(sc, cm); 2910216088Sken if ((error != 0) && (error != EINPROGRESS)) { 2911253460Sscottl mps_dprint(sc, MPS_ERROR, 2912253460Sscottl "%s: error %d returned from mps_map_command()\n", 2913216088Sken __func__, error); 2914216088Sken goto bailout_error; 2915216088Sken } 2916216088Sken 2917216088Sken return; 2918216088Sken 2919216088Skenbailout_error: 2920216088Sken mps_free_command(sc, cm); 2921216088Sken ccb->ccb_h.status = CAM_RESRC_UNAVAIL; 2922216088Sken xpt_done(ccb); 2923216088Sken return; 2924216088Sken 2925216088Sken} 2926216088Sken 2927216088Skenstatic void 2928216088Skenmpssas_action_smpio(struct mpssas_softc *sassc, union ccb *ccb) 2929216088Sken{ 2930216088Sken struct mps_softc *sc; 2931216088Sken struct mpssas_target *targ; 2932216088Sken uint64_t sasaddr = 0; 2933216088Sken 2934216088Sken sc = sassc->sc; 2935216088Sken 2936216088Sken /* 2937216088Sken * Make sure the target exists. 2938216088Sken */ 2939216088Sken targ = &sassc->targets[ccb->ccb_h.target_id]; 2940216088Sken if (targ->handle == 0x0) { 2941253460Sscottl mps_dprint(sc, MPS_ERROR, 2942253460Sscottl "%s: target %d does not exist!\n", __func__, 2943216088Sken ccb->ccb_h.target_id); 2944216088Sken ccb->ccb_h.status = CAM_SEL_TIMEOUT; 2945216088Sken xpt_done(ccb); 2946216088Sken return; 2947216088Sken } 2948216088Sken 2949216088Sken /* 2950216088Sken * If this device has an embedded SMP target, we'll talk to it 2951216088Sken * directly. 2952216088Sken * figure out what the expander's address is. 2953216088Sken */ 2954216088Sken if ((targ->devinfo & MPI2_SAS_DEVICE_INFO_SMP_TARGET) != 0) 2955216088Sken sasaddr = targ->sasaddr; 2956216088Sken 2957216088Sken /* 2958216088Sken * If we don't have a SAS address for the expander yet, try 2959216088Sken * grabbing it from the page 0x83 information cached in the 2960216088Sken * transport layer for this target. LSI expanders report the 2961216088Sken * expander SAS address as the port-associated SAS address in 2962216088Sken * Inquiry VPD page 0x83. Maxim expanders don't report it in page 2963216088Sken * 0x83. 2964216088Sken * 2965216088Sken * XXX KDM disable this for now, but leave it commented out so that 2966216088Sken * it is obvious that this is another possible way to get the SAS 2967216088Sken * address. 2968216088Sken * 2969216088Sken * The parent handle method below is a little more reliable, and 2970216088Sken * the other benefit is that it works for devices other than SES 2971216088Sken * devices. So you can send a SMP request to a da(4) device and it 2972216088Sken * will get routed to the expander that device is attached to. 2973216088Sken * (Assuming the da(4) device doesn't contain an SMP target...) 2974216088Sken */ 2975216088Sken#if 0 2976216088Sken if (sasaddr == 0) 2977216088Sken sasaddr = xpt_path_sas_addr(ccb->ccb_h.path); 2978216088Sken#endif 2979216088Sken 2980216088Sken /* 2981216088Sken * If we still don't have a SAS address for the expander, look for 2982216088Sken * the parent device of this device, which is probably the expander. 2983216088Sken */ 2984216088Sken if (sasaddr == 0) { 2985230592Sken#ifdef OLD_MPS_PROBE 2986216088Sken struct mpssas_target *parent_target; 2987230592Sken#endif 2988216088Sken 2989216088Sken if (targ->parent_handle == 0x0) { 2990253460Sscottl mps_dprint(sc, MPS_ERROR, 2991253460Sscottl "%s: handle %d does not have a valid " 2992216088Sken "parent handle!\n", __func__, targ->handle); 2993216088Sken ccb->ccb_h.status = CAM_REQ_INVALID; 2994216088Sken goto bailout; 2995216088Sken } 2996230592Sken#ifdef OLD_MPS_PROBE 2997230592Sken parent_target = mpssas_find_target_by_handle(sassc, 0, 2998230592Sken targ->parent_handle); 2999216088Sken 3000216088Sken if (parent_target == NULL) { 3001253460Sscottl mps_dprint(sc, MPS_ERROR, 3002253460Sscottl "%s: handle %d does not have a valid " 3003216088Sken "parent target!\n", __func__, targ->handle); 3004216088Sken ccb->ccb_h.status = CAM_REQ_INVALID; 3005216088Sken goto bailout; 3006216088Sken } 3007216088Sken 3008216088Sken if ((parent_target->devinfo & 3009216088Sken MPI2_SAS_DEVICE_INFO_SMP_TARGET) == 0) { 3010253460Sscottl mps_dprint(sc, MPS_ERROR, 3011253460Sscottl "%s: handle %d parent %d does not " 3012216088Sken "have an SMP target!\n", __func__, 3013216088Sken targ->handle, parent_target->handle); 3014216088Sken ccb->ccb_h.status = CAM_REQ_INVALID; 3015216088Sken goto bailout; 3016216088Sken 3017216088Sken } 3018216088Sken 3019216088Sken sasaddr = parent_target->sasaddr; 3020230592Sken#else /* OLD_MPS_PROBE */ 3021230592Sken if ((targ->parent_devinfo & 3022230592Sken MPI2_SAS_DEVICE_INFO_SMP_TARGET) == 0) { 3023253460Sscottl mps_dprint(sc, MPS_ERROR, 3024253460Sscottl "%s: handle %d parent %d does not " 3025230592Sken "have an SMP target!\n", __func__, 3026230592Sken targ->handle, targ->parent_handle); 3027230592Sken ccb->ccb_h.status = CAM_REQ_INVALID; 3028230592Sken goto bailout; 3029230592Sken 3030230592Sken } 3031230592Sken if (targ->parent_sasaddr == 0x0) { 3032253460Sscottl mps_dprint(sc, MPS_ERROR, 3033253460Sscottl "%s: handle %d parent handle %d does " 3034230592Sken "not have a valid SAS address!\n", 3035230592Sken __func__, targ->handle, targ->parent_handle); 3036230592Sken ccb->ccb_h.status = CAM_REQ_INVALID; 3037230592Sken goto bailout; 3038230592Sken } 3039230592Sken 3040230592Sken sasaddr = targ->parent_sasaddr; 3041230592Sken#endif /* OLD_MPS_PROBE */ 3042230592Sken 3043216088Sken } 3044216088Sken 3045216088Sken if (sasaddr == 0) { 3046253460Sscottl mps_dprint(sc, MPS_INFO, 3047253460Sscottl "%s: unable to find SAS address for handle %d\n", 3048216088Sken __func__, targ->handle); 3049216088Sken ccb->ccb_h.status = CAM_REQ_INVALID; 3050216088Sken goto bailout; 3051216088Sken } 3052216088Sken mpssas_send_smpcmd(sassc, ccb, sasaddr); 3053216088Sken 3054216088Sken return; 3055216088Sken 3056216088Skenbailout: 3057216088Sken xpt_done(ccb); 3058216088Sken 3059216088Sken} 3060230592Sken#endif //__FreeBSD_version >= 900026 3061216088Sken 3062216088Skenstatic void 3063212420Skenmpssas_action_resetdev(struct mpssas_softc *sassc, union ccb *ccb) 3064212420Sken{ 3065230592Sken MPI2_SCSI_TASK_MANAGE_REQUEST *req; 3066212420Sken struct mps_softc *sc; 3067230592Sken struct mps_command *tm; 3068212420Sken struct mpssas_target *targ; 3069212420Sken 3070253460Sscottl MPS_FUNCTRACE(sassc->sc); 3071230592Sken mtx_assert(&sassc->sc->mps_mtx, MA_OWNED); 3072230592Sken 3073212420Sken sc = sassc->sc; 3074230592Sken tm = mps_alloc_command(sc); 3075230592Sken if (tm == NULL) { 3076253460Sscottl mps_dprint(sc, MPS_ERROR, 3077253809Sscottl "command alloc failure in mpssas_action_resetdev\n"); 3078212420Sken ccb->ccb_h.status = CAM_RESRC_UNAVAIL; 3079212420Sken xpt_done(ccb); 3080212420Sken return; 3081212420Sken } 3082212420Sken 3083230592Sken targ = &sassc->targets[ccb->ccb_h.target_id]; 3084230592Sken req = (MPI2_SCSI_TASK_MANAGE_REQUEST *)tm->cm_req; 3085237683Sken req->DevHandle = htole16(targ->handle); 3086212420Sken req->Function = MPI2_FUNCTION_SCSI_TASK_MGMT; 3087212420Sken req->TaskType = MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET; 3088212420Sken 3089212420Sken /* SAS Hard Link Reset / SATA Link Reset */ 3090212420Sken req->MsgFlags = MPI2_SCSITASKMGMT_MSGFLAGS_LINK_RESET; 3091212420Sken 3092230592Sken tm->cm_data = NULL; 3093230592Sken tm->cm_desc.HighPriority.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_HIGH_PRIORITY; 3094230592Sken tm->cm_complete = mpssas_resetdev_complete; 3095230592Sken tm->cm_complete_data = ccb; 3096238969Smav tm->cm_targ = targ; 3097230592Sken mps_map_command(sc, tm); 3098212420Sken} 3099212420Sken 3100212420Skenstatic void 3101230592Skenmpssas_resetdev_complete(struct mps_softc *sc, struct mps_command *tm) 3102212420Sken{ 3103212420Sken MPI2_SCSI_TASK_MANAGE_REPLY *resp; 3104212420Sken union ccb *ccb; 3105212420Sken 3106253460Sscottl MPS_FUNCTRACE(sc); 3107230592Sken mtx_assert(&sc->mps_mtx, MA_OWNED); 3108212420Sken 3109230592Sken resp = (MPI2_SCSI_TASK_MANAGE_REPLY *)tm->cm_reply; 3110230592Sken ccb = tm->cm_complete_data; 3111212420Sken 3112230592Sken /* 3113230592Sken * Currently there should be no way we can hit this case. It only 3114230592Sken * happens when we have a failure to allocate chain frames, and 3115230592Sken * task management commands don't have S/G lists. 3116230592Sken */ 3117230592Sken if ((tm->cm_flags & MPS_CM_FLAGS_ERROR_MASK) != 0) { 3118218812Sken MPI2_SCSI_TASK_MANAGE_REQUEST *req; 3119218812Sken 3120230592Sken req = (MPI2_SCSI_TASK_MANAGE_REQUEST *)tm->cm_req; 3121218812Sken 3122253460Sscottl mps_dprint(sc, MPS_ERROR, 3123253460Sscottl "%s: cm_flags = %#x for reset of handle %#04x! " 3124230592Sken "This should not happen!\n", __func__, tm->cm_flags, 3125218812Sken req->DevHandle); 3126218812Sken ccb->ccb_h.status = CAM_REQ_CMP_ERR; 3127218812Sken goto bailout; 3128218812Sken } 3129218812Sken 3130253460Sscottl mps_dprint(sc, MPS_XINFO, 3131253460Sscottl "%s: IOCStatus = 0x%x ResponseCode = 0x%x\n", __func__, 3132237683Sken le16toh(resp->IOCStatus), le32toh(resp->ResponseCode)); 3133212420Sken 3134237683Sken if (le32toh(resp->ResponseCode) == MPI2_SCSITASKMGMT_RSP_TM_COMPLETE) { 3135212420Sken ccb->ccb_h.status = CAM_REQ_CMP; 3136230592Sken mpssas_announce_reset(sc, AC_SENT_BDR, tm->cm_targ->tid, 3137230592Sken CAM_LUN_WILDCARD); 3138230592Sken } 3139212420Sken else 3140212420Sken ccb->ccb_h.status = CAM_REQ_CMP_ERR; 3141212420Sken 3142218812Skenbailout: 3143212772Sken 3144230592Sken mpssas_free_tm(sc, tm); 3145212420Sken xpt_done(ccb); 3146212420Sken} 3147212420Sken 3148212420Skenstatic void 3149212420Skenmpssas_poll(struct cam_sim *sim) 3150212420Sken{ 3151212420Sken struct mpssas_softc *sassc; 3152212420Sken 3153212420Sken sassc = cam_sim_softc(sim); 3154230592Sken 3155230592Sken if (sassc->sc->mps_debug & MPS_TRACE) { 3156230592Sken /* frequent debug messages during a panic just slow 3157230592Sken * everything down too much. 3158230592Sken */ 3159230592Sken mps_printf(sassc->sc, "%s clearing MPS_TRACE\n", __func__); 3160230592Sken sassc->sc->mps_debug &= ~MPS_TRACE; 3161230592Sken } 3162230592Sken 3163212420Sken mps_intr_locked(sassc->sc); 3164212420Sken} 3165212420Sken 3166212420Skenstatic void 3167230592Skenmpssas_async(void *callback_arg, uint32_t code, struct cam_path *path, 3168230592Sken void *arg) 3169230592Sken{ 3170230592Sken struct mps_softc *sc; 3171230592Sken 3172230592Sken sc = (struct mps_softc *)callback_arg; 3173230592Sken 3174230592Sken switch (code) { 3175253549Sken#if (__FreeBSD_version >= 1000006) || \ 3176253549Sken ((__FreeBSD_version >= 901503) && (__FreeBSD_version < 1000000)) 3177230592Sken case AC_ADVINFO_CHANGED: { 3178230592Sken struct mpssas_target *target; 3179230592Sken struct mpssas_softc *sassc; 3180230592Sken struct scsi_read_capacity_data_long rcap_buf; 3181230592Sken struct ccb_dev_advinfo cdai; 3182230592Sken struct mpssas_lun *lun; 3183230592Sken lun_id_t lunid; 3184230592Sken int found_lun; 3185230592Sken uintptr_t buftype; 3186230592Sken 3187230592Sken buftype = (uintptr_t)arg; 3188230592Sken 3189230592Sken found_lun = 0; 3190230592Sken sassc = sc->sassc; 3191230592Sken 3192230592Sken /* 3193230592Sken * We're only interested in read capacity data changes. 3194230592Sken */ 3195230592Sken if (buftype != CDAI_TYPE_RCAPLONG) 3196230592Sken break; 3197230592Sken 3198230592Sken /* 3199230592Sken * We should have a handle for this, but check to make sure. 3200230592Sken */ 3201230592Sken target = &sassc->targets[xpt_path_target_id(path)]; 3202230592Sken if (target->handle == 0) 3203230592Sken break; 3204230592Sken 3205230592Sken lunid = xpt_path_lun_id(path); 3206230592Sken 3207230592Sken SLIST_FOREACH(lun, &target->luns, lun_link) { 3208230592Sken if (lun->lun_id == lunid) { 3209230592Sken found_lun = 1; 3210230592Sken break; 3211230592Sken } 3212230592Sken } 3213230592Sken 3214230592Sken if (found_lun == 0) { 3215230592Sken lun = malloc(sizeof(struct mpssas_lun), M_MPT2, 3216230592Sken M_NOWAIT | M_ZERO); 3217230592Sken if (lun == NULL) { 3218253460Sscottl mps_dprint(sc, MPS_ERROR, "Unable to alloc " 3219230592Sken "LUN for EEDP support.\n"); 3220230592Sken break; 3221230592Sken } 3222230592Sken lun->lun_id = lunid; 3223230592Sken SLIST_INSERT_HEAD(&target->luns, lun, lun_link); 3224230592Sken } 3225230592Sken 3226230592Sken bzero(&rcap_buf, sizeof(rcap_buf)); 3227230592Sken xpt_setup_ccb(&cdai.ccb_h, path, CAM_PRIORITY_NORMAL); 3228230592Sken cdai.ccb_h.func_code = XPT_DEV_ADVINFO; 3229230592Sken cdai.ccb_h.flags = CAM_DIR_IN; 3230230592Sken cdai.buftype = CDAI_TYPE_RCAPLONG; 3231230592Sken cdai.flags = 0; 3232230592Sken cdai.bufsiz = sizeof(rcap_buf); 3233230592Sken cdai.buf = (uint8_t *)&rcap_buf; 3234230592Sken xpt_action((union ccb *)&cdai); 3235230592Sken if ((cdai.ccb_h.status & CAM_DEV_QFRZN) != 0) 3236230592Sken cam_release_devq(cdai.ccb_h.path, 3237230592Sken 0, 0, 0, FALSE); 3238230592Sken 3239230592Sken if (((cdai.ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP) 3240230592Sken && (rcap_buf.prot & SRC16_PROT_EN)) { 3241230592Sken lun->eedp_formatted = TRUE; 3242230592Sken lun->eedp_block_size = scsi_4btoul(rcap_buf.length); 3243230592Sken } else { 3244230592Sken lun->eedp_formatted = FALSE; 3245230592Sken lun->eedp_block_size = 0; 3246230592Sken } 3247230592Sken break; 3248230592Sken } 3249253549Sken#else 3250253549Sken case AC_FOUND_DEVICE: { 3251253549Sken struct ccb_getdev *cgd; 3252253549Sken 3253253549Sken cgd = arg; 3254253549Sken mpssas_check_eedp(sc, path, cgd); 3255253549Sken break; 3256253549Sken } 3257253549Sken#endif 3258230592Sken default: 3259230592Sken break; 3260230592Sken } 3261230592Sken} 3262230592Sken 3263253549Sken#if (__FreeBSD_version < 901503) || \ 3264253549Sken ((__FreeBSD_version >= 1000000) && (__FreeBSD_version < 1000006)) 3265230592Skenstatic void 3266253549Skenmpssas_check_eedp(struct mps_softc *sc, struct cam_path *path, 3267253549Sken struct ccb_getdev *cgd) 3268230592Sken{ 3269253549Sken struct mpssas_softc *sassc = sc->sassc; 3270230592Sken struct ccb_scsiio *csio; 3271230592Sken struct scsi_read_capacity_16 *scsi_cmd; 3272230592Sken struct scsi_read_capacity_eedp *rcap_buf; 3273253549Sken path_id_t pathid; 3274230592Sken target_id_t targetid; 3275230592Sken lun_id_t lunid; 3276253549Sken union ccb *ccb; 3277253549Sken struct cam_path *local_path; 3278230592Sken struct mpssas_target *target; 3279230592Sken struct mpssas_lun *lun; 3280230592Sken uint8_t found_lun; 3281237683Sken char path_str[64]; 3282230592Sken 3283253549Sken sassc = sc->sassc; 3284253549Sken pathid = cam_sim_path(sassc->sim); 3285253549Sken targetid = xpt_path_target_id(path); 3286253549Sken lunid = xpt_path_lun_id(path); 3287253549Sken 3288253549Sken target = &sassc->targets[targetid]; 3289253549Sken if (target->handle == 0x0) 3290253549Sken return; 3291253549Sken 3292230592Sken /* 3293253549Sken * Determine if the device is EEDP capable. 3294253549Sken * 3295253549Sken * If this flag is set in the inquiry data, 3296253549Sken * the device supports protection information, 3297253549Sken * and must support the 16 byte read 3298253549Sken * capacity command, otherwise continue without 3299253549Sken * sending read cap 16 3300230592Sken */ 3301253549Sken if ((cgd->inq_data.spc3_flags & SPC3_SID_PROTECT) == 0) 3302253549Sken return; 3303230592Sken 3304253549Sken /* 3305253549Sken * Issue a READ CAPACITY 16 command. This info 3306253549Sken * is used to determine if the LUN is formatted 3307253549Sken * for EEDP support. 3308253549Sken */ 3309253549Sken ccb = xpt_alloc_ccb_nowait(); 3310253549Sken if (ccb == NULL) { 3311253549Sken mps_dprint(sc, MPS_ERROR, "Unable to alloc CCB " 3312253549Sken "for EEDP support.\n"); 3313253549Sken return; 3314253549Sken } 3315230592Sken 3316253549Sken if (xpt_create_path(&local_path, xpt_periph, 3317253549Sken pathid, targetid, lunid) != CAM_REQ_CMP) { 3318253549Sken mps_dprint(sc, MPS_ERROR, "Unable to create " 3319253549Sken "path for EEDP support\n"); 3320253549Sken xpt_free_ccb(ccb); 3321253549Sken return; 3322253549Sken } 3323230592Sken 3324253549Sken /* 3325253549Sken * If LUN is already in list, don't create a new 3326253549Sken * one. 3327253549Sken */ 3328253549Sken found_lun = FALSE; 3329253549Sken SLIST_FOREACH(lun, &target->luns, lun_link) { 3330253549Sken if (lun->lun_id == lunid) { 3331253549Sken found_lun = TRUE; 3332253549Sken break; 3333253549Sken } 3334253549Sken } 3335253549Sken if (!found_lun) { 3336253549Sken lun = malloc(sizeof(struct mpssas_lun), M_MPT2, 3337253549Sken M_NOWAIT | M_ZERO); 3338253549Sken if (lun == NULL) { 3339253549Sken mps_dprint(sc, MPS_ERROR, 3340253549Sken "Unable to alloc LUN for EEDP support.\n"); 3341253549Sken xpt_free_path(local_path); 3342253549Sken xpt_free_ccb(ccb); 3343253549Sken return; 3344253549Sken } 3345253549Sken lun->lun_id = lunid; 3346253549Sken SLIST_INSERT_HEAD(&target->luns, lun, 3347253549Sken lun_link); 3348253549Sken } 3349230592Sken 3350253549Sken xpt_path_string(local_path, path_str, sizeof(path_str)); 3351253549Sken mps_dprint(sc, MPS_INFO, "Sending read cap: path %s handle %d\n", 3352253549Sken path_str, target->handle); 3353237683Sken 3354253549Sken /* 3355253549Sken * Issue a READ CAPACITY 16 command for the LUN. 3356253549Sken * The mpssas_read_cap_done function will load 3357253549Sken * the read cap info into the LUN struct. 3358253549Sken */ 3359253549Sken rcap_buf = malloc(sizeof(struct scsi_read_capacity_eedp), 3360253549Sken M_MPT2, M_NOWAIT | M_ZERO); 3361253549Sken if (rcap_buf == NULL) { 3362253549Sken mps_dprint(sc, MPS_FAULT, 3363253549Sken "Unable to alloc read capacity buffer for EEDP support.\n"); 3364253549Sken xpt_free_path(ccb->ccb_h.path); 3365253549Sken xpt_free_ccb(ccb); 3366253549Sken return; 3367253549Sken } 3368253549Sken xpt_setup_ccb(&ccb->ccb_h, local_path, CAM_PRIORITY_XPT); 3369253549Sken csio = &ccb->csio; 3370253549Sken csio->ccb_h.func_code = XPT_SCSI_IO; 3371253549Sken csio->ccb_h.flags = CAM_DIR_IN; 3372253549Sken csio->ccb_h.retry_count = 4; 3373253549Sken csio->ccb_h.cbfcnp = mpssas_read_cap_done; 3374253549Sken csio->ccb_h.timeout = 60000; 3375253549Sken csio->data_ptr = (uint8_t *)rcap_buf; 3376253549Sken csio->dxfer_len = sizeof(struct scsi_read_capacity_eedp); 3377253549Sken csio->sense_len = MPS_SENSE_LEN; 3378253549Sken csio->cdb_len = sizeof(*scsi_cmd); 3379253549Sken csio->tag_action = MSG_SIMPLE_Q_TAG; 3380237683Sken 3381253549Sken scsi_cmd = (struct scsi_read_capacity_16 *)&csio->cdb_io.cdb_bytes; 3382253549Sken bzero(scsi_cmd, sizeof(*scsi_cmd)); 3383253549Sken scsi_cmd->opcode = 0x9E; 3384253549Sken scsi_cmd->service_action = SRC16_SERVICE_ACTION; 3385253549Sken ((uint8_t *)scsi_cmd)[13] = sizeof(struct scsi_read_capacity_eedp); 3386230592Sken 3387253549Sken ccb->ccb_h.ppriv_ptr1 = sassc; 3388253549Sken xpt_action(ccb); 3389230592Sken} 3390230592Sken 3391230592Skenstatic void 3392230592Skenmpssas_read_cap_done(struct cam_periph *periph, union ccb *done_ccb) 3393230592Sken{ 3394230592Sken struct mpssas_softc *sassc; 3395230592Sken struct mpssas_target *target; 3396230592Sken struct mpssas_lun *lun; 3397230592Sken struct scsi_read_capacity_eedp *rcap_buf; 3398230592Sken 3399230592Sken if (done_ccb == NULL) 3400230592Sken return; 3401231240Sken 3402231240Sken /* Driver need to release devq, it Scsi command is 3403231240Sken * generated by driver internally. 3404231240Sken * Currently there is a single place where driver 3405231240Sken * calls scsi command internally. In future if driver 3406231240Sken * calls more scsi command internally, it needs to release 3407231240Sken * devq internally, since those command will not go back to 3408231240Sken * cam_periph. 3409231240Sken */ 3410231240Sken if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) ) { 3411231240Sken done_ccb->ccb_h.status &= ~CAM_DEV_QFRZN; 3412231240Sken xpt_release_devq(done_ccb->ccb_h.path, 3413231240Sken /*count*/ 1, /*run_queue*/TRUE); 3414231240Sken } 3415230592Sken 3416230592Sken rcap_buf = (struct scsi_read_capacity_eedp *)done_ccb->csio.data_ptr; 3417230592Sken 3418230592Sken /* 3419230592Sken * Get the LUN ID for the path and look it up in the LUN list for the 3420230592Sken * target. 3421230592Sken */ 3422230592Sken sassc = (struct mpssas_softc *)done_ccb->ccb_h.ppriv_ptr1; 3423230592Sken target = &sassc->targets[done_ccb->ccb_h.target_id]; 3424230592Sken SLIST_FOREACH(lun, &target->luns, lun_link) { 3425230592Sken if (lun->lun_id != done_ccb->ccb_h.target_lun) 3426230592Sken continue; 3427230592Sken 3428230592Sken /* 3429230592Sken * Got the LUN in the target's LUN list. Fill it in 3430230592Sken * with EEDP info. If the READ CAP 16 command had some 3431230592Sken * SCSI error (common if command is not supported), mark 3432230592Sken * the lun as not supporting EEDP and set the block size 3433230592Sken * to 0. 3434230592Sken */ 3435230592Sken if (((done_ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) 3436230592Sken || (done_ccb->csio.scsi_status != SCSI_STATUS_OK)) { 3437230592Sken lun->eedp_formatted = FALSE; 3438230592Sken lun->eedp_block_size = 0; 3439230592Sken break; 3440230592Sken } 3441230592Sken 3442230592Sken if (rcap_buf->protect & 0x01) { 3443253550Sken mps_dprint(sassc->sc, MPS_INFO, "LUN %d for " 3444253550Sken "target ID %d is formatted for EEDP " 3445253550Sken "support.\n", done_ccb->ccb_h.target_lun, 3446253550Sken done_ccb->ccb_h.target_id); 3447230592Sken lun->eedp_formatted = TRUE; 3448230592Sken lun->eedp_block_size = scsi_4btoul(rcap_buf->length); 3449230592Sken } 3450230592Sken break; 3451230592Sken } 3452230592Sken 3453230592Sken // Finished with this CCB and path. 3454230592Sken free(rcap_buf, M_MPT2); 3455230592Sken xpt_free_path(done_ccb->ccb_h.path); 3456230592Sken xpt_free_ccb(done_ccb); 3457230592Sken} 3458253549Sken#endif /* (__FreeBSD_version < 901503) || \ 3459253549Sken ((__FreeBSD_version >= 1000000) && (__FreeBSD_version < 1000006)) */ 3460230592Sken 3461230592Skenint 3462230592Skenmpssas_startup(struct mps_softc *sc) 3463230592Sken{ 3464230592Sken struct mpssas_softc *sassc; 3465230592Sken 3466230592Sken /* 3467230592Sken * Send the port enable message and set the wait_for_port_enable flag. 3468230592Sken * This flag helps to keep the simq frozen until all discovery events 3469230592Sken * are processed. 3470230592Sken */ 3471230592Sken sassc = sc->sassc; 3472230592Sken mpssas_startup_increment(sassc); 3473230592Sken sc->wait_for_port_enable = 1; 3474230592Sken mpssas_send_portenable(sc); 3475230592Sken return (0); 3476230592Sken} 3477230592Sken 3478230592Skenstatic int 3479230592Skenmpssas_send_portenable(struct mps_softc *sc) 3480230592Sken{ 3481230592Sken MPI2_PORT_ENABLE_REQUEST *request; 3482230592Sken struct mps_command *cm; 3483230592Sken 3484253460Sscottl MPS_FUNCTRACE(sc); 3485230592Sken 3486230592Sken if ((cm = mps_alloc_command(sc)) == NULL) 3487230592Sken return (EBUSY); 3488230592Sken request = (MPI2_PORT_ENABLE_REQUEST *)cm->cm_req; 3489230592Sken request->Function = MPI2_FUNCTION_PORT_ENABLE; 3490230592Sken request->MsgFlags = 0; 3491230592Sken request->VP_ID = 0; 3492230592Sken cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 3493230592Sken cm->cm_complete = mpssas_portenable_complete; 3494230592Sken cm->cm_data = NULL; 3495230592Sken cm->cm_sge = NULL; 3496230592Sken 3497230592Sken mps_map_command(sc, cm); 3498253460Sscottl mps_dprint(sc, MPS_XINFO, 3499230592Sken "mps_send_portenable finished cm %p req %p complete %p\n", 3500230592Sken cm, cm->cm_req, cm->cm_complete); 3501230592Sken return (0); 3502230592Sken} 3503230592Sken 3504230592Skenstatic void 3505230592Skenmpssas_portenable_complete(struct mps_softc *sc, struct mps_command *cm) 3506230592Sken{ 3507230592Sken MPI2_PORT_ENABLE_REPLY *reply; 3508230592Sken struct mpssas_softc *sassc; 3509230592Sken 3510253460Sscottl MPS_FUNCTRACE(sc); 3511230592Sken sassc = sc->sassc; 3512230592Sken 3513230592Sken /* 3514230592Sken * Currently there should be no way we can hit this case. It only 3515230592Sken * happens when we have a failure to allocate chain frames, and 3516230592Sken * port enable commands don't have S/G lists. 3517230592Sken */ 3518230592Sken if ((cm->cm_flags & MPS_CM_FLAGS_ERROR_MASK) != 0) { 3519253460Sscottl mps_dprint(sc, MPS_ERROR, "%s: cm_flags = %#x for port enable! " 3520230592Sken "This should not happen!\n", __func__, cm->cm_flags); 3521230592Sken } 3522230592Sken 3523230592Sken reply = (MPI2_PORT_ENABLE_REPLY *)cm->cm_reply; 3524230592Sken if (reply == NULL) 3525230592Sken mps_dprint(sc, MPS_FAULT, "Portenable NULL reply\n"); 3526237683Sken else if (le16toh(reply->IOCStatus & MPI2_IOCSTATUS_MASK) != 3527230592Sken MPI2_IOCSTATUS_SUCCESS) 3528230592Sken mps_dprint(sc, MPS_FAULT, "Portenable failed\n"); 3529230592Sken 3530230592Sken mps_free_command(sc, cm); 3531230592Sken if (sc->mps_ich.ich_arg != NULL) { 3532253460Sscottl mps_dprint(sc, MPS_XINFO, "disestablish config intrhook\n"); 3533230592Sken config_intrhook_disestablish(&sc->mps_ich); 3534230592Sken sc->mps_ich.ich_arg = NULL; 3535230592Sken } 3536230592Sken 3537230592Sken /* 3538230592Sken * Get WarpDrive info after discovery is complete but before the scan 3539230592Sken * starts. At this point, all devices are ready to be exposed to the 3540230592Sken * OS. If devices should be hidden instead, take them out of the 3541230592Sken * 'targets' array before the scan. The devinfo for a disk will have 3542230592Sken * some info and a volume's will be 0. Use that to remove disks. 3543230592Sken */ 3544230592Sken mps_wd_config_pages(sc); 3545230592Sken 3546230592Sken /* 3547230592Sken * Done waiting for port enable to complete. Decrement the refcount. 3548230592Sken * If refcount is 0, discovery is complete and a rescan of the bus can 3549230592Sken * take place. Since the simq was explicitly frozen before port 3550230592Sken * enable, it must be explicitly released here to keep the 3551230592Sken * freeze/release count in sync. 3552230592Sken */ 3553230592Sken sc->wait_for_port_enable = 0; 3554230592Sken sc->port_enable_complete = 1; 3555237683Sken wakeup(&sc->port_enable_complete); 3556230592Sken mpssas_startup_decrement(sassc); 3557230592Sken xpt_release_simq(sassc->sim, 1); 3558230592Sken} 3559230592Sken 3560254116Sscottlint 3561254116Sscottlmpssas_check_id(struct mpssas_softc *sassc, int id) 3562254116Sscottl{ 3563254116Sscottl struct mps_softc *sc = sassc->sc; 3564254116Sscottl char *ids; 3565254116Sscottl char *name; 3566254116Sscottl 3567254116Sscottl ids = &sc->exclude_ids[0]; 3568254116Sscottl while((name = strsep(&ids, ",")) != NULL) { 3569254116Sscottl if (name[0] == '\0') 3570254116Sscottl continue; 3571254116Sscottl if (strtol(name, NULL, 0) == (long)id) 3572254116Sscottl return (1); 3573254116Sscottl } 3574254116Sscottl 3575254116Sscottl return (0); 3576254116Sscottl} 3577