1212420Sken/*- 2212420Sken * Copyright (c) 2009 Yahoo! Inc. 3237876Sken * 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. 26230920Sken * 27230920Sken * LSI MPT-Fusion Host Adapter FreeBSD 28230920Sken * 29230920Sken * $FreeBSD$ 30230920Sken */ 31212420Sken 32212420Sken#include <sys/cdefs.h> 33212420Sken__FBSDID("$FreeBSD$"); 34212420Sken 35212420Sken/* Communications core for LSI MPT2 */ 36212420Sken 37230920Sken/* 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> 51230920Sken#include <sys/queue.h> 52230920Sken#include <sys/kthread.h> 53230920Sken#include <sys/taskqueue.h> 54230920Sken#include <sys/sbuf.h> 55212420Sken 56212420Sken#include <machine/bus.h> 57212420Sken#include <machine/resource.h> 58212420Sken#include <sys/rman.h> 59212420Sken 60230920Sken#include <machine/stdarg.h> 61230920Sken 62212420Sken#include <cam/cam.h> 63212420Sken#include <cam/cam_ccb.h> 64230920Sken#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> 82230920Sken#include <dev/mps/mpi/mpi2_tool.h> 83230920Sken#include <dev/mps/mps_ioctl.h> 84212420Sken#include <dev/mps/mpsvar.h> 85212420Sken#include <dev/mps/mps_table.h> 86230920Sken#include <dev/mps/mps_sas.h> 87212420Sken 88230920Sken#define MPSSAS_DISCOVERY_TIMEOUT 20 89230920Sken#define MPSSAS_MAX_DISCOVERY_TIMEOUTS 10 /* 200 seconds */ 90212420Sken 91230920Sken/* 92230920Sken * static array to check SCSI OpCode for EEDP protection bits 93230920Sken */ 94230920Sken#define PRO_R MPI2_SCSIIO_EEDPFLAGS_CHECK_REMOVE_OP 95230920Sken#define PRO_W MPI2_SCSIIO_EEDPFLAGS_INSERT_OP 96230920Sken#define PRO_V MPI2_SCSIIO_EEDPFLAGS_INSERT_OP 97230920Skenstatic uint8_t op_code_prot[256] = { 98230920Sken 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 99230920Sken 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 100230920Sken 0, 0, 0, 0, 0, 0, 0, 0, PRO_R, 0, PRO_W, 0, 0, 0, PRO_W, PRO_V, 101230920Sken 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 102230920Sken 0, PRO_W, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 103230920Sken 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 104230920Sken 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 105230920Sken 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 106230920Sken 0, 0, 0, 0, 0, 0, 0, 0, PRO_R, 0, PRO_W, 0, 0, 0, PRO_W, PRO_V, 107230920Sken 0, 0, 0, PRO_W, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 108230920Sken 0, 0, 0, 0, 0, 0, 0, 0, PRO_R, 0, PRO_W, 0, 0, 0, PRO_W, PRO_V, 109230920Sken 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 110230920Sken 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 111230920Sken 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 112230920Sken 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 113230920Sken 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 114212420Sken}; 115212420Sken 116212420SkenMALLOC_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); 125230920Skenstatic void mpssas_direct_drive_io(struct mpssas_softc *sassc, 126230920Sken 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 *); 129230920Skenstatic 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); 135230920Sken#endif //FreeBSD_version >= 900026 136212420Skenstatic void mpssas_resetdev_complete(struct mps_softc *, struct mps_command *); 137230920Skenstatic int mpssas_send_abort(struct mps_softc *sc, struct mps_command *tm, struct mps_command *cm); 138230920Skenstatic int mpssas_send_reset(struct mps_softc *sc, struct mps_command *tm, uint8_t type); 139230920Skenstatic void mpssas_async(void *callback_arg, uint32_t code, 140230920Sken struct cam_path *path, void *arg); 141254938Sken#if (__FreeBSD_version < 901503) || \ 142254938Sken ((__FreeBSD_version >= 1000000) && (__FreeBSD_version < 1000006)) 143254938Skenstatic void mpssas_check_eedp(struct mps_softc *sc, struct cam_path *path, 144254938Sken struct ccb_getdev *cgd); 145230920Skenstatic void mpssas_read_cap_done(struct cam_periph *periph, union ccb *done_ccb); 146230920Sken#endif 147230920Skenstatic int mpssas_send_portenable(struct mps_softc *sc); 148230920Skenstatic void mpssas_portenable_complete(struct mps_softc *sc, 149230920Sken struct mps_command *cm); 150212420Sken 151231679Skenstruct mpssas_target * 152230920Skenmpssas_find_target_by_handle(struct mpssas_softc *sassc, int start, uint16_t handle) 153216368Sken{ 154230920Sken struct mpssas_target *target; 155230920Sken int i; 156216368Sken 157230920Sken for (i = start; i < sassc->sc->facts->MaxTargets; i++) { 158230920Sken target = &sassc->targets[i]; 159230920Sken if (target->handle == handle) 160230920Sken return (target); 161216368Sken } 162216368Sken 163230920Sken return (NULL); 164216368Sken} 165216368Sken 166230920Sken/* we need to freeze the simq during attach and diag reset, to avoid failing 167230920Sken * commands before device handles have been found by discovery. Since 168230920Sken * discovery involves reading config pages and possibly sending commands, 169230920Sken * discovery actions may continue even after we receive the end of discovery 170230920Sken * event, so refcount discovery actions instead of assuming we can unfreeze 171230920Sken * the simq when we get the event. 172230920Sken */ 173230920Skenvoid 174230920Skenmpssas_startup_increment(struct mpssas_softc *sassc) 175212420Sken{ 176254938Sken MPS_FUNCTRACE(sassc->sc); 177254938Sken 178230920Sken if ((sassc->flags & MPSSAS_IN_STARTUP) != 0) { 179230920Sken if (sassc->startup_refcount++ == 0) { 180230920Sken /* just starting, freeze the simq */ 181254938Sken mps_dprint(sassc->sc, MPS_INIT, 182230920Sken "%s freezing simq\n", __func__); 183262857Smav#if (__FreeBSD_version >= 1000039) || \ 184262857Smav ((__FreeBSD_version < 1000000) && (__FreeBSD_version >= 902502)) 185262857Smav xpt_hold_boot(); 186262857Smav#endif 187230920Sken xpt_freeze_simq(sassc->sim, 1); 188230920Sken } 189254938Sken mps_dprint(sassc->sc, MPS_INIT, "%s refcount %u\n", __func__, 190230920Sken sassc->startup_refcount); 191230920Sken } 192230920Sken} 193212420Sken 194230920Skenvoid 195230920Skenmpssas_startup_decrement(struct mpssas_softc *sassc) 196230920Sken{ 197254938Sken MPS_FUNCTRACE(sassc->sc); 198254938Sken 199230920Sken if ((sassc->flags & MPSSAS_IN_STARTUP) != 0) { 200230920Sken if (--sassc->startup_refcount == 0) { 201230920Sken /* finished all discovery-related actions, release 202230920Sken * the simq and rescan for the latest topology. 203230920Sken */ 204254938Sken mps_dprint(sassc->sc, MPS_INIT, 205230920Sken "%s releasing simq\n", __func__); 206230920Sken sassc->flags &= ~MPSSAS_IN_STARTUP; 207262857Smav xpt_release_simq(sassc->sim, 1); 208254938Sken#if (__FreeBSD_version >= 1000039) || \ 209254938Sken ((__FreeBSD_version < 1000000) && (__FreeBSD_version >= 902502)) 210254938Sken xpt_release_boot(); 211254938Sken#else 212230920Sken mpssas_rescan_target(sassc->sc, NULL); 213254938Sken#endif 214230920Sken } 215254938Sken mps_dprint(sassc->sc, MPS_INIT, "%s refcount %u\n", __func__, 216230920Sken sassc->startup_refcount); 217212420Sken } 218230920Sken} 219212420Sken 220230920Sken/* LSI's firmware requires us to stop sending commands when we're doing task 221230920Sken * management, so refcount the TMs and keep the simq frozen when any are in 222230920Sken * use. 223230920Sken */ 224230920Skenstruct mps_command * 225230920Skenmpssas_alloc_tm(struct mps_softc *sc) 226230920Sken{ 227230920Sken struct mps_command *tm; 228212420Sken 229254938Sken MPS_FUNCTRACE(sc); 230230920Sken tm = mps_alloc_high_priority_command(sc); 231230920Sken if (tm != NULL) { 232230920Sken if (sc->sassc->tm_count++ == 0) { 233254938Sken mps_dprint(sc, MPS_RECOVERY, 234254938Sken "%s freezing simq\n", __func__); 235230920Sken xpt_freeze_simq(sc->sassc->sim, 1); 236230920Sken } 237254938Sken mps_dprint(sc, MPS_RECOVERY, "%s tm_count %u\n", __func__, 238230920Sken sc->sassc->tm_count); 239230920Sken } 240230920Sken return tm; 241212420Sken} 242212420Sken 243230920Skenvoid 244230920Skenmpssas_free_tm(struct mps_softc *sc, struct mps_command *tm) 245212420Sken{ 246254938Sken mps_dprint(sc, MPS_TRACE, "%s", __func__); 247230920Sken if (tm == NULL) 248230920Sken return; 249212420Sken 250230920Sken /* if there are no TMs in use, we can release the simq. We use our 251230920Sken * own refcount so that it's easier for a diag reset to cleanup and 252230920Sken * release the simq. 253230920Sken */ 254230920Sken if (--sc->sassc->tm_count == 0) { 255254938Sken mps_dprint(sc, MPS_RECOVERY, "%s releasing simq\n", __func__); 256230920Sken xpt_release_simq(sc->sassc->sim, 1); 257212420Sken } 258254938Sken mps_dprint(sc, MPS_RECOVERY, "%s tm_count %u\n", __func__, 259230920Sken sc->sassc->tm_count); 260212420Sken 261230920Sken mps_free_high_priority_command(sc, tm); 262212420Sken} 263212420Sken 264230920Skenvoid 265230920Skenmpssas_rescan_target(struct mps_softc *sc, struct mpssas_target *targ) 266212420Sken{ 267230920Sken struct mpssas_softc *sassc = sc->sassc; 268230920Sken path_id_t pathid; 269230920Sken target_id_t targetid; 270230920Sken union ccb *ccb; 271212420Sken 272254938Sken MPS_FUNCTRACE(sc); 273230920Sken pathid = cam_sim_path(sassc->sim); 274230920Sken if (targ == NULL) 275230920Sken targetid = CAM_TARGET_WILDCARD; 276230920Sken else 277230920Sken targetid = targ - sassc->targets; 278212420Sken 279230920Sken /* 280230920Sken * Allocate a CCB and schedule a rescan. 281230920Sken */ 282230920Sken ccb = xpt_alloc_ccb_nowait(); 283230920Sken if (ccb == NULL) { 284254938Sken mps_dprint(sc, MPS_ERROR, "unable to alloc CCB for rescan\n"); 285212420Sken return; 286212420Sken } 287212420Sken 288253037Smav if (xpt_create_path(&ccb->ccb_h.path, NULL, pathid, 289254938Sken targetid, CAM_LUN_WILDCARD) != CAM_REQ_CMP) { 290254938Sken mps_dprint(sc, MPS_ERROR, "unable to create path for rescan\n"); 291230920Sken xpt_free_ccb(ccb); 292212420Sken return; 293212420Sken } 294230920Sken 295237947Sken if (targetid == CAM_TARGET_WILDCARD) 296237947Sken ccb->ccb_h.func_code = XPT_SCAN_BUS; 297237947Sken else 298237947Sken ccb->ccb_h.func_code = XPT_SCAN_TGT; 299237947Sken 300230920Sken mps_dprint(sc, MPS_TRACE, "%s targetid %u\n", __func__, targetid); 301254938Sken xpt_rescan(ccb); 302212420Sken} 303212420Sken 304212420Skenstatic void 305254938Skenmpssas_log_command(struct mps_command *cm, u_int level, const char *fmt, ...) 306212420Sken{ 307230920Sken struct sbuf sb; 308230920Sken va_list ap; 309230920Sken char str[192]; 310230920Sken char path_str[64]; 311212420Sken 312230920Sken if (cm == NULL) 313230920Sken return; 314212420Sken 315256236Smav /* No need to be in here if debugging isn't enabled */ 316256236Smav if ((cm->cm_sc->mps_debug & level) == 0) 317256236Smav return; 318256236Smav 319230920Sken sbuf_new(&sb, str, sizeof(str), 0); 320212420Sken 321230920Sken va_start(ap, fmt); 322212420Sken 323230920Sken if (cm->cm_ccb != NULL) { 324230920Sken xpt_path_string(cm->cm_ccb->csio.ccb_h.path, path_str, 325230920Sken sizeof(path_str)); 326230920Sken sbuf_cat(&sb, path_str); 327230920Sken if (cm->cm_ccb->ccb_h.func_code == XPT_SCSI_IO) { 328230920Sken scsi_command_string(&cm->cm_ccb->csio, &sb); 329230920Sken sbuf_printf(&sb, "length %d ", 330230920Sken cm->cm_ccb->csio.dxfer_len); 331212420Sken } 332212420Sken } 333230920Sken else { 334230920Sken sbuf_printf(&sb, "(noperiph:%s%d:%u:%u:%u): ", 335230920Sken cam_sim_name(cm->cm_sc->sassc->sim), 336230920Sken cam_sim_unit(cm->cm_sc->sassc->sim), 337230920Sken cam_sim_bus(cm->cm_sc->sassc->sim), 338230920Sken cm->cm_targ ? cm->cm_targ->tid : 0xFFFFFFFF, 339230920Sken cm->cm_lun); 340230920Sken } 341212420Sken 342230920Sken sbuf_printf(&sb, "SMID %u ", cm->cm_desc.Default.SMID); 343230920Sken sbuf_vprintf(&sb, fmt, ap); 344230920Sken sbuf_finish(&sb); 345254938Sken mps_dprint_field(cm->cm_sc, level, "%s", sbuf_data(&sb)); 346212420Sken 347230920Sken va_end(ap); 348230920Sken} 349212420Sken 350231679Sken 351230920Skenstatic void 352231679Skenmpssas_remove_volume(struct mps_softc *sc, struct mps_command *tm) 353230920Sken{ 354231679Sken MPI2_SCSI_TASK_MANAGE_REPLY *reply; 355231679Sken struct mpssas_target *targ; 356231679Sken uint16_t handle; 357212420Sken 358254938Sken MPS_FUNCTRACE(sc); 359231679Sken 360231679Sken reply = (MPI2_SCSI_TASK_MANAGE_REPLY *)tm->cm_reply; 361231679Sken handle = (uint16_t)(uintptr_t)tm->cm_complete_data; 362231679Sken targ = tm->cm_targ; 363231679Sken 364231679Sken if (reply == NULL) { 365231679Sken /* XXX retry the remove after the diag reset completes? */ 366254938Sken mps_dprint(sc, MPS_FAULT, 367254938Sken "%s NULL reply reseting device 0x%04x\n", __func__, handle); 368231679Sken mpssas_free_tm(sc, tm); 369230920Sken return; 370230920Sken } 371212420Sken 372231679Sken if (reply->IOCStatus != MPI2_IOCSTATUS_SUCCESS) { 373254938Sken mps_dprint(sc, MPS_FAULT, 374254938Sken "IOCStatus = 0x%x while resetting device 0x%x\n", 375231679Sken reply->IOCStatus, handle); 376231679Sken mpssas_free_tm(sc, tm); 377231679Sken return; 378231679Sken } 379231679Sken 380254938Sken mps_dprint(sc, MPS_XINFO, 381254938Sken "Reset aborted %u commands\n", reply->TerminationCount); 382231679Sken mps_free_reply(sc, tm->cm_reply_data); 383240579Seadler tm->cm_reply = NULL; /* Ensures the reply won't get re-freed */ 384231679Sken 385254938Sken mps_dprint(sc, MPS_XINFO, 386254938Sken "clearing target %u handle 0x%04x\n", targ->tid, handle); 387231679Sken 388231679Sken /* 389231679Sken * Don't clear target if remove fails because things will get confusing. 390231679Sken * Leave the devname and sasaddr intact so that we know to avoid reusing 391231679Sken * this target id if possible, and so we can assign the same target id 392231679Sken * to this device if it comes back in the future. 393231679Sken */ 394231679Sken if (reply->IOCStatus == MPI2_IOCSTATUS_SUCCESS) { 395231679Sken targ = tm->cm_targ; 396231679Sken targ->handle = 0x0; 397231679Sken targ->encl_handle = 0x0; 398231679Sken targ->encl_slot = 0x0; 399231679Sken targ->exp_dev_handle = 0x0; 400231679Sken targ->phy_num = 0x0; 401231679Sken targ->linkrate = 0x0; 402231679Sken targ->devinfo = 0x0; 403231679Sken targ->flags = 0x0; 404231679Sken } 405231679Sken 406231679Sken mpssas_free_tm(sc, tm); 407212420Sken} 408212420Sken 409231679Sken 410212420Sken/* 411231679Sken * No Need to call "MPI2_SAS_OP_REMOVE_DEVICE" For Volume removal. 412231679Sken * Otherwise Volume Delete is same as Bare Drive Removal. 413231679Sken */ 414231679Skenvoid 415231679Skenmpssas_prepare_volume_remove(struct mpssas_softc *sassc, uint16_t handle) 416231679Sken{ 417231679Sken MPI2_SCSI_TASK_MANAGE_REQUEST *req; 418231679Sken struct mps_softc *sc; 419231679Sken struct mps_command *cm; 420231679Sken struct mpssas_target *targ = NULL; 421231679Sken 422254938Sken MPS_FUNCTRACE(sassc->sc); 423231679Sken sc = sassc->sc; 424231679Sken 425231679Sken#ifdef WD_SUPPORT 426231679Sken /* 427231679Sken * If this is a WD controller, determine if the disk should be exposed 428231679Sken * to the OS or not. If disk should be exposed, return from this 429231679Sken * function without doing anything. 430231679Sken */ 431231679Sken if (sc->WD_available && (sc->WD_hide_expose == 432231679Sken MPS_WD_EXPOSE_ALWAYS)) { 433231679Sken return; 434231679Sken } 435231679Sken#endif //WD_SUPPORT 436231679Sken 437231679Sken targ = mpssas_find_target_by_handle(sassc, 0, handle); 438231679Sken if (targ == NULL) { 439231679Sken /* FIXME: what is the action? */ 440231679Sken /* We don't know about this device? */ 441254938Sken mps_dprint(sc, MPS_ERROR, 442254938Sken "%s %d : invalid handle 0x%x \n", __func__,__LINE__, handle); 443231679Sken return; 444231679Sken } 445231679Sken 446231679Sken targ->flags |= MPSSAS_TARGET_INREMOVAL; 447231679Sken 448231679Sken cm = mpssas_alloc_tm(sc); 449231679Sken if (cm == NULL) { 450254938Sken mps_dprint(sc, MPS_ERROR, 451254938Sken "%s: command alloc failure\n", __func__); 452231679Sken return; 453231679Sken } 454231679Sken 455231679Sken mpssas_rescan_target(sc, targ); 456231679Sken 457231679Sken req = (MPI2_SCSI_TASK_MANAGE_REQUEST *)cm->cm_req; 458231679Sken req->DevHandle = targ->handle; 459231679Sken req->Function = MPI2_FUNCTION_SCSI_TASK_MGMT; 460231679Sken req->TaskType = MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET; 461231679Sken 462231679Sken /* SAS Hard Link Reset / SATA Link Reset */ 463231679Sken req->MsgFlags = MPI2_SCSITASKMGMT_MSGFLAGS_LINK_RESET; 464231679Sken 465231679Sken cm->cm_targ = targ; 466231679Sken cm->cm_data = NULL; 467231679Sken cm->cm_desc.HighPriority.RequestFlags = 468231679Sken MPI2_REQ_DESCRIPT_FLAGS_HIGH_PRIORITY; 469231679Sken cm->cm_complete = mpssas_remove_volume; 470231679Sken cm->cm_complete_data = (void *)(uintptr_t)handle; 471231679Sken mps_map_command(sc, cm); 472231679Sken} 473231679Sken 474231679Sken/* 475230920Sken * The MPT2 firmware performs debounce on the link to avoid transient link 476230920Sken * errors and false removals. When it does decide that link has been lost 477230920Sken * and a device need to go away, it expects that the host will perform a 478230920Sken * target reset and then an op remove. The reset has the side-effect of 479230920Sken * aborting any outstanding requests for the device, which is required for 480230920Sken * the op-remove to succeed. It's not clear if the host should check for 481230920Sken * the device coming back alive after the reset. 482212420Sken */ 483230920Skenvoid 484230920Skenmpssas_prepare_remove(struct mpssas_softc *sassc, uint16_t handle) 485212420Sken{ 486212420Sken MPI2_SCSI_TASK_MANAGE_REQUEST *req; 487212420Sken struct mps_softc *sc; 488212420Sken struct mps_command *cm; 489212420Sken struct mpssas_target *targ = NULL; 490212420Sken 491254938Sken MPS_FUNCTRACE(sassc->sc); 492212420Sken 493230920Sken sc = sassc->sc; 494230920Sken 495230920Sken targ = mpssas_find_target_by_handle(sassc, 0, handle); 496230920Sken if (targ == NULL) { 497230920Sken /* FIXME: what is the action? */ 498212420Sken /* We don't know about this device? */ 499254938Sken mps_dprint(sc, MPS_ERROR, 500254938Sken "%s : invalid handle 0x%x \n", __func__, handle); 501212420Sken return; 502230920Sken } 503212420Sken 504230920Sken targ->flags |= MPSSAS_TARGET_INREMOVAL; 505230920Sken 506230920Sken cm = mpssas_alloc_tm(sc); 507212420Sken if (cm == NULL) { 508254938Sken mps_dprint(sc, MPS_ERROR, 509254938Sken "%s: command alloc failure\n", __func__); 510212420Sken return; 511212420Sken } 512212420Sken 513231679Sken mpssas_rescan_target(sc, targ); 514218811Sken 515212420Sken req = (MPI2_SCSI_TASK_MANAGE_REQUEST *)cm->cm_req; 516218811Sken memset(req, 0, sizeof(*req)); 517237876Sken req->DevHandle = htole16(targ->handle); 518212420Sken req->Function = MPI2_FUNCTION_SCSI_TASK_MGMT; 519212420Sken req->TaskType = MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET; 520212420Sken 521212420Sken /* SAS Hard Link Reset / SATA Link Reset */ 522212420Sken req->MsgFlags = MPI2_SCSITASKMGMT_MSGFLAGS_LINK_RESET; 523212420Sken 524230920Sken cm->cm_targ = targ; 525212420Sken cm->cm_data = NULL; 526230920Sken cm->cm_desc.HighPriority.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_HIGH_PRIORITY; 527212420Sken cm->cm_complete = mpssas_remove_device; 528230920Sken cm->cm_complete_data = (void *)(uintptr_t)handle; 529230920Sken mps_map_command(sc, cm); 530212420Sken} 531212420Sken 532212420Skenstatic void 533230920Skenmpssas_remove_device(struct mps_softc *sc, struct mps_command *tm) 534212420Sken{ 535212420Sken MPI2_SCSI_TASK_MANAGE_REPLY *reply; 536212420Sken MPI2_SAS_IOUNIT_CONTROL_REQUEST *req; 537212420Sken struct mpssas_target *targ; 538218811Sken struct mps_command *next_cm; 539212420Sken uint16_t handle; 540212420Sken 541254938Sken MPS_FUNCTRACE(sc); 542212420Sken 543230920Sken reply = (MPI2_SCSI_TASK_MANAGE_REPLY *)tm->cm_reply; 544230920Sken handle = (uint16_t)(uintptr_t)tm->cm_complete_data; 545230920Sken targ = tm->cm_targ; 546213535Sken 547218812Sken /* 548218812Sken * Currently there should be no way we can hit this case. It only 549218812Sken * happens when we have a failure to allocate chain frames, and 550218812Sken * task management commands don't have S/G lists. 551218812Sken */ 552230920Sken if ((tm->cm_flags & MPS_CM_FLAGS_ERROR_MASK) != 0) { 553254938Sken mps_dprint(sc, MPS_ERROR, 554254938Sken "%s: cm_flags = %#x for remove of handle %#04x! " 555254938Sken "This should not happen!\n", __func__, tm->cm_flags, 556254938Sken handle); 557230920Sken mpssas_free_tm(sc, tm); 558218812Sken return; 559218812Sken } 560218812Sken 561230920Sken if (reply == NULL) { 562230920Sken /* XXX retry the remove after the diag reset completes? */ 563254938Sken mps_dprint(sc, MPS_FAULT, 564254938Sken "%s NULL reply reseting device 0x%04x\n", __func__, handle); 565230920Sken mpssas_free_tm(sc, tm); 566230920Sken return; 567230920Sken } 568230920Sken 569237876Sken if (le16toh(reply->IOCStatus) != MPI2_IOCSTATUS_SUCCESS) { 570254938Sken mps_dprint(sc, MPS_FAULT, 571254938Sken "IOCStatus = 0x%x while resetting device 0x%x\n", 572237876Sken le16toh(reply->IOCStatus), handle); 573230920Sken mpssas_free_tm(sc, tm); 574212420Sken return; 575212420Sken } 576212420Sken 577254938Sken mps_dprint(sc, MPS_XINFO, "Reset aborted %u commands\n", 578237876Sken le32toh(reply->TerminationCount)); 579230920Sken mps_free_reply(sc, tm->cm_reply_data); 580240579Seadler tm->cm_reply = NULL; /* Ensures the reply won't get re-freed */ 581212420Sken 582212420Sken /* Reuse the existing command */ 583230920Sken req = (MPI2_SAS_IOUNIT_CONTROL_REQUEST *)tm->cm_req; 584218811Sken memset(req, 0, sizeof(*req)); 585212420Sken req->Function = MPI2_FUNCTION_SAS_IO_UNIT_CONTROL; 586212420Sken req->Operation = MPI2_SAS_OP_REMOVE_DEVICE; 587237876Sken req->DevHandle = htole16(handle); 588230920Sken tm->cm_data = NULL; 589230920Sken tm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 590230920Sken tm->cm_complete = mpssas_remove_complete; 591230920Sken tm->cm_complete_data = (void *)(uintptr_t)handle; 592212420Sken 593230920Sken mps_map_command(sc, tm); 594212420Sken 595254938Sken mps_dprint(sc, MPS_XINFO, "clearing target %u handle 0x%04x\n", 596230920Sken targ->tid, handle); 597230920Sken TAILQ_FOREACH_SAFE(tm, &targ->commands, cm_link, next_cm) { 598218811Sken union ccb *ccb; 599218811Sken 600254938Sken mps_dprint(sc, MPS_XINFO, "Completing missed command %p\n", tm); 601230920Sken ccb = tm->cm_complete_data; 602218811Sken ccb->ccb_h.status = CAM_DEV_NOT_THERE; 603230920Sken mpssas_scsiio_complete(sc, tm); 604218811Sken } 605212420Sken} 606212420Sken 607212420Skenstatic void 608230920Skenmpssas_remove_complete(struct mps_softc *sc, struct mps_command *tm) 609212420Sken{ 610212420Sken MPI2_SAS_IOUNIT_CONTROL_REPLY *reply; 611230920Sken uint16_t handle; 612230920Sken struct mpssas_target *targ; 613237876Sken struct mpssas_lun *lun; 614212420Sken 615254938Sken MPS_FUNCTRACE(sc); 616212420Sken 617230920Sken reply = (MPI2_SAS_IOUNIT_CONTROL_REPLY *)tm->cm_reply; 618230920Sken handle = (uint16_t)(uintptr_t)tm->cm_complete_data; 619212420Sken 620230920Sken /* 621230920Sken * Currently there should be no way we can hit this case. It only 622230920Sken * happens when we have a failure to allocate chain frames, and 623230920Sken * task management commands don't have S/G lists. 624230920Sken */ 625230920Sken if ((tm->cm_flags & MPS_CM_FLAGS_ERROR_MASK) != 0) { 626254938Sken mps_dprint(sc, MPS_XINFO, 627254938Sken "%s: cm_flags = %#x for remove of handle %#04x! " 628230920Sken "This should not happen!\n", __func__, tm->cm_flags, 629230920Sken handle); 630230920Sken mpssas_free_tm(sc, tm); 631230920Sken return; 632230920Sken } 633212420Sken 634230920Sken if (reply == NULL) { 635230920Sken /* most likely a chip reset */ 636254938Sken mps_dprint(sc, MPS_FAULT, 637254938Sken "%s NULL reply removing device 0x%04x\n", __func__, handle); 638230920Sken mpssas_free_tm(sc, tm); 639230920Sken return; 640212420Sken } 641212420Sken 642254938Sken mps_dprint(sc, MPS_XINFO, 643254938Sken "%s on handle 0x%04x, IOCStatus= 0x%x\n", __func__, 644237876Sken handle, le16toh(reply->IOCStatus)); 645212420Sken 646230920Sken /* 647230920Sken * Don't clear target if remove fails because things will get confusing. 648230920Sken * Leave the devname and sasaddr intact so that we know to avoid reusing 649230920Sken * this target id if possible, and so we can assign the same target id 650230920Sken * to this device if it comes back in the future. 651230920Sken */ 652237876Sken if (le16toh(reply->IOCStatus) == MPI2_IOCSTATUS_SUCCESS) { 653230920Sken targ = tm->cm_targ; 654230920Sken targ->handle = 0x0; 655230920Sken targ->encl_handle = 0x0; 656230920Sken targ->encl_slot = 0x0; 657230920Sken targ->exp_dev_handle = 0x0; 658230920Sken targ->phy_num = 0x0; 659230920Sken targ->linkrate = 0x0; 660230920Sken targ->devinfo = 0x0; 661231679Sken targ->flags = 0x0; 662237876Sken 663237876Sken while(!SLIST_EMPTY(&targ->luns)) { 664237876Sken lun = SLIST_FIRST(&targ->luns); 665237876Sken SLIST_REMOVE_HEAD(&targ->luns, lun_link); 666237876Sken free(lun, M_MPT2); 667237876Sken } 668212420Sken } 669237876Sken 670212420Sken 671230920Sken mpssas_free_tm(sc, tm); 672212420Sken} 673212420Sken 674212420Skenstatic int 675212420Skenmpssas_register_events(struct mps_softc *sc) 676212420Sken{ 677237876Sken u32 events[MPI2_EVENT_NOTIFY_EVENTMASK_WORDS]; 678212420Sken 679212420Sken bzero(events, 16); 680212420Sken setbit(events, MPI2_EVENT_SAS_DEVICE_STATUS_CHANGE); 681212420Sken setbit(events, MPI2_EVENT_SAS_DISCOVERY); 682212420Sken setbit(events, MPI2_EVENT_SAS_BROADCAST_PRIMITIVE); 683212420Sken setbit(events, MPI2_EVENT_SAS_INIT_DEVICE_STATUS_CHANGE); 684212420Sken setbit(events, MPI2_EVENT_SAS_INIT_TABLE_OVERFLOW); 685212420Sken setbit(events, MPI2_EVENT_SAS_TOPOLOGY_CHANGE_LIST); 686212420Sken setbit(events, MPI2_EVENT_SAS_ENCL_DEVICE_STATUS_CHANGE); 687230920Sken setbit(events, MPI2_EVENT_IR_CONFIGURATION_CHANGE_LIST); 688230920Sken setbit(events, MPI2_EVENT_IR_VOLUME); 689230920Sken setbit(events, MPI2_EVENT_IR_PHYSICAL_DISK); 690230920Sken setbit(events, MPI2_EVENT_IR_OPERATION_STATUS); 691230920Sken setbit(events, MPI2_EVENT_LOG_ENTRY_ADDED); 692212420Sken 693212420Sken mps_register_events(sc, events, mpssas_evt_handler, NULL, 694212420Sken &sc->sassc->mpssas_eh); 695212420Sken 696212420Sken return (0); 697212420Sken} 698212420Sken 699212420Skenint 700212420Skenmps_attach_sas(struct mps_softc *sc) 701212420Sken{ 702212420Sken struct mpssas_softc *sassc; 703230920Sken cam_status status; 704230920Sken int unit, error = 0; 705212420Sken 706254938Sken MPS_FUNCTRACE(sc); 707212420Sken 708212420Sken sassc = malloc(sizeof(struct mpssas_softc), M_MPT2, M_WAITOK|M_ZERO); 709237876Sken if(!sassc) { 710237876Sken device_printf(sc->mps_dev, "Cannot allocate memory %s %d\n", 711237876Sken __func__, __LINE__); 712237876Sken return (ENOMEM); 713237876Sken } 714212420Sken sassc->targets = malloc(sizeof(struct mpssas_target) * 715212420Sken sc->facts->MaxTargets, M_MPT2, M_WAITOK|M_ZERO); 716237876Sken if(!sassc->targets) { 717237876Sken device_printf(sc->mps_dev, "Cannot allocate memory %s %d\n", 718237876Sken __func__, __LINE__); 719237876Sken free(sassc, M_MPT2); 720237876Sken return (ENOMEM); 721237876Sken } 722212420Sken sc->sassc = sassc; 723212420Sken sassc->sc = sc; 724212420Sken 725230920Sken if ((sassc->devq = cam_simq_alloc(sc->num_reqs)) == NULL) { 726254938Sken mps_dprint(sc, MPS_ERROR, "Cannot allocate SIMQ\n"); 727212420Sken error = ENOMEM; 728212420Sken goto out; 729212420Sken } 730212420Sken 731230920Sken unit = device_get_unit(sc->mps_dev); 732212420Sken sassc->sim = cam_sim_alloc(mpssas_action, mpssas_poll, "mps", sassc, 733230920Sken unit, &sc->mps_mtx, sc->num_reqs, sc->num_reqs, sassc->devq); 734212420Sken if (sassc->sim == NULL) { 735254938Sken mps_dprint(sc, MPS_ERROR, "Cannot allocate SIM\n"); 736212420Sken error = EINVAL; 737212420Sken goto out; 738212420Sken } 739212420Sken 740230920Sken TAILQ_INIT(&sassc->ev_queue); 741230920Sken 742230920Sken /* Initialize taskqueue for Event Handling */ 743230920Sken TASK_INIT(&sassc->ev_task, 0, mpssas_firmware_event_work, sc); 744230920Sken sassc->ev_tq = taskqueue_create("mps_taskq", M_NOWAIT | M_ZERO, 745230920Sken taskqueue_thread_enqueue, &sassc->ev_tq); 746230920Sken 747230920Sken /* Run the task queue with lowest priority */ 748230920Sken taskqueue_start_threads(&sassc->ev_tq, 1, 255, "%s taskq", 749230920Sken device_get_nameunit(sc->mps_dev)); 750230920Sken 751230920Sken mps_lock(sc); 752230920Sken 753212420Sken /* 754212420Sken * XXX There should be a bus for every port on the adapter, but since 755212420Sken * we're just going to fake the topology for now, we'll pretend that 756212420Sken * everything is just a target on a single bus. 757212420Sken */ 758212420Sken if ((error = xpt_bus_register(sassc->sim, sc->mps_dev, 0)) != 0) { 759254938Sken mps_dprint(sc, MPS_ERROR, "Error %d registering SCSI bus\n", 760212420Sken error); 761212420Sken mps_unlock(sc); 762212420Sken goto out; 763212420Sken } 764212420Sken 765212420Sken /* 766254938Sken * Assume that discovery events will start right away. 767254938Sken * 768254938Sken * Hold off boot until discovery is complete. 769212420Sken */ 770230920Sken sassc->flags |= MPSSAS_IN_STARTUP | MPSSAS_IN_DISCOVERY; 771230920Sken sc->sassc->startup_refcount = 0; 772262857Smav mpssas_startup_increment(sassc); 773212420Sken 774212420Sken callout_init(&sassc->discovery_callout, 1 /*mpsafe*/); 775212420Sken sassc->discovery_timeouts = 0; 776212420Sken 777230920Sken sassc->tm_count = 0; 778230920Sken 779254938Sken /* 780254938Sken * Register for async events so we can determine the EEDP 781254938Sken * capabilities of devices. 782254938Sken */ 783254938Sken status = xpt_create_path(&sassc->path, /*periph*/NULL, 784254938Sken cam_sim_path(sc->sassc->sim), CAM_TARGET_WILDCARD, 785254938Sken CAM_LUN_WILDCARD); 786230920Sken if (status != CAM_REQ_CMP) { 787254938Sken mps_printf(sc, "Error %#x creating sim path\n", status); 788254938Sken sassc->path = NULL; 789254938Sken } else { 790254938Sken int event; 791254938Sken 792254938Sken#if (__FreeBSD_version >= 1000006) || \ 793254938Sken ((__FreeBSD_version >= 901503) && (__FreeBSD_version < 1000000)) 794254938Sken event = AC_ADVINFO_CHANGED; 795254938Sken#else 796254938Sken event = AC_FOUND_DEVICE; 797254938Sken#endif 798254938Sken status = xpt_register_async(event, mpssas_async, sc, 799254938Sken sassc->path); 800254938Sken if (status != CAM_REQ_CMP) { 801254938Sken mps_dprint(sc, MPS_ERROR, 802254938Sken "Error %#x registering async handler for " 803254938Sken "AC_ADVINFO_CHANGED events\n", status); 804254938Sken xpt_free_path(sassc->path); 805254938Sken sassc->path = NULL; 806254938Sken } 807230920Sken } 808254938Sken if (status != CAM_REQ_CMP) { 809254938Sken /* 810254938Sken * EEDP use is the exception, not the rule. 811254938Sken * Warn the user, but do not fail to attach. 812254938Sken */ 813254938Sken mps_printf(sc, "EEDP capabilities disabled.\n"); 814254938Sken } 815230920Sken 816230920Sken mps_unlock(sc); 817230920Sken 818212420Sken mpssas_register_events(sc); 819212420Skenout: 820212420Sken if (error) 821212420Sken mps_detach_sas(sc); 822212420Sken return (error); 823212420Sken} 824212420Sken 825212420Skenint 826212420Skenmps_detach_sas(struct mps_softc *sc) 827212420Sken{ 828212420Sken struct mpssas_softc *sassc; 829237876Sken struct mpssas_lun *lun, *lun_tmp; 830237876Sken struct mpssas_target *targ; 831237876Sken int i; 832212420Sken 833254938Sken MPS_FUNCTRACE(sc); 834212420Sken 835212420Sken if (sc->sassc == NULL) 836212420Sken return (0); 837212420Sken 838212420Sken sassc = sc->sassc; 839230920Sken mps_deregister_events(sc, sassc->mpssas_eh); 840212420Sken 841230920Sken /* 842230920Sken * Drain and free the event handling taskqueue with the lock 843230920Sken * unheld so that any parallel processing tasks drain properly 844230920Sken * without deadlocking. 845230920Sken */ 846230920Sken if (sassc->ev_tq != NULL) 847230920Sken taskqueue_free(sassc->ev_tq); 848230920Sken 849212420Sken /* Make sure CAM doesn't wedge if we had to bail out early. */ 850212420Sken mps_lock(sc); 851230920Sken 852230920Sken /* Deregister our async handler */ 853254938Sken if (sassc->path != NULL) { 854254938Sken xpt_register_async(0, mpssas_async, sc, sassc->path); 855254938Sken xpt_free_path(sassc->path); 856254938Sken sassc->path = NULL; 857254938Sken } 858230920Sken 859212420Sken if (sassc->flags & MPSSAS_IN_STARTUP) 860212420Sken xpt_release_simq(sassc->sim, 1); 861212420Sken 862212420Sken if (sassc->sim != NULL) { 863212420Sken xpt_bus_deregister(cam_sim_path(sassc->sim)); 864212420Sken cam_sim_free(sassc->sim, FALSE); 865212420Sken } 866230920Sken 867254938Sken sassc->flags |= MPSSAS_SHUTDOWN; 868212420Sken mps_unlock(sc); 869212420Sken 870212420Sken if (sassc->devq != NULL) 871212420Sken cam_simq_free(sassc->devq); 872212420Sken 873237876Sken for(i=0; i< sc->facts->MaxTargets ;i++) { 874237876Sken targ = &sassc->targets[i]; 875237876Sken SLIST_FOREACH_SAFE(lun, &targ->luns, lun_link, lun_tmp) { 876237876Sken free(lun, M_MPT2); 877237876Sken } 878237876Sken } 879212420Sken free(sassc->targets, M_MPT2); 880212420Sken free(sassc, M_MPT2); 881212420Sken sc->sassc = NULL; 882212420Sken 883212420Sken return (0); 884212420Sken} 885212420Sken 886230920Skenvoid 887212420Skenmpssas_discovery_end(struct mpssas_softc *sassc) 888212420Sken{ 889212420Sken struct mps_softc *sc = sassc->sc; 890212420Sken 891254938Sken MPS_FUNCTRACE(sc); 892212420Sken 893212420Sken if (sassc->flags & MPSSAS_DISCOVERY_TIMEOUT_PENDING) 894212420Sken callout_stop(&sassc->discovery_callout); 895212420Sken 896212420Sken} 897212420Sken 898212420Skenstatic void 899230920Skenmpssas_discovery_timeout(void *data) 900212420Sken{ 901230920Sken struct mpssas_softc *sassc = data; 902230920Sken struct mps_softc *sc; 903212420Sken 904230920Sken sc = sassc->sc; 905254938Sken MPS_FUNCTRACE(sc); 906212420Sken 907230920Sken mps_lock(sc); 908254938Sken mps_dprint(sc, MPS_INFO, 909230920Sken "Timeout waiting for discovery, interrupts may not be working!\n"); 910230920Sken sassc->flags &= ~MPSSAS_DISCOVERY_TIMEOUT_PENDING; 911212420Sken 912230920Sken /* Poll the hardware for events in case interrupts aren't working */ 913230920Sken mps_intr_locked(sc); 914212420Sken 915254938Sken mps_dprint(sassc->sc, MPS_INFO, 916230920Sken "Finished polling after discovery timeout at %d\n", ticks); 917230920Sken 918212420Sken if ((sassc->flags & MPSSAS_IN_DISCOVERY) == 0) { 919212420Sken mpssas_discovery_end(sassc); 920212420Sken } else { 921212420Sken if (sassc->discovery_timeouts < MPSSAS_MAX_DISCOVERY_TIMEOUTS) { 922212420Sken sassc->flags |= MPSSAS_DISCOVERY_TIMEOUT_PENDING; 923212420Sken callout_reset(&sassc->discovery_callout, 924212420Sken MPSSAS_DISCOVERY_TIMEOUT * hz, 925212420Sken mpssas_discovery_timeout, sassc); 926212420Sken sassc->discovery_timeouts++; 927212420Sken } else { 928212420Sken mps_dprint(sassc->sc, MPS_FAULT, 929212420Sken "Discovery timed out, continuing.\n"); 930212420Sken sassc->flags &= ~MPSSAS_IN_DISCOVERY; 931212420Sken mpssas_discovery_end(sassc); 932212420Sken } 933212420Sken } 934212420Sken 935212420Sken mps_unlock(sc); 936212420Sken} 937212420Sken 938212420Skenstatic void 939212420Skenmpssas_action(struct cam_sim *sim, union ccb *ccb) 940212420Sken{ 941212420Sken struct mpssas_softc *sassc; 942212420Sken 943212420Sken sassc = cam_sim_softc(sim); 944212420Sken 945254938Sken MPS_FUNCTRACE(sassc->sc); 946254938Sken mps_dprint(sassc->sc, MPS_TRACE, "ccb func_code 0x%x\n", 947212420Sken ccb->ccb_h.func_code); 948230920Sken mtx_assert(&sassc->sc->mps_mtx, MA_OWNED); 949212420Sken 950212420Sken switch (ccb->ccb_h.func_code) { 951212420Sken case XPT_PATH_INQ: 952212420Sken { 953212420Sken struct ccb_pathinq *cpi = &ccb->cpi; 954212420Sken 955212420Sken cpi->version_num = 1; 956212420Sken cpi->hba_inquiry = PI_SDTR_ABLE|PI_TAG_ABLE|PI_WIDE_16; 957212420Sken cpi->target_sprt = 0; 958254938Sken#if (__FreeBSD_version >= 1000039) || \ 959254938Sken ((__FreeBSD_version < 1000000) && (__FreeBSD_version >= 902502)) 960254938Sken cpi->hba_misc = PIM_NOBUSRESET | PIM_UNMAPPED | PIM_NOSCAN; 961254938Sken#else 962251899Sscottl cpi->hba_misc = PIM_NOBUSRESET | PIM_UNMAPPED; 963254938Sken#endif 964212420Sken cpi->hba_eng_cnt = 0; 965212420Sken cpi->max_target = sassc->sc->facts->MaxTargets - 1; 966237876Sken cpi->max_lun = 255; 967256234Smav cpi->initiator_id = sassc->sc->facts->MaxTargets - 1; 968212420Sken strncpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN); 969212420Sken strncpy(cpi->hba_vid, "LSILogic", HBA_IDLEN); 970212420Sken strncpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN); 971212420Sken cpi->unit_number = cam_sim_unit(sim); 972212420Sken cpi->bus_id = cam_sim_bus(sim); 973212420Sken cpi->base_transfer_speed = 150000; 974212420Sken cpi->transport = XPORT_SAS; 975212420Sken cpi->transport_version = 0; 976212420Sken cpi->protocol = PROTO_SCSI; 977212420Sken cpi->protocol_version = SCSI_REV_SPC; 978230920Sken#if __FreeBSD_version >= 800001 979230920Sken /* 980230920Sken * XXX KDM where does this number come from? 981230920Sken */ 982230920Sken cpi->maxio = 256 * 1024; 983230920Sken#endif 984212420Sken cpi->ccb_h.status = CAM_REQ_CMP; 985212420Sken break; 986212420Sken } 987212420Sken case XPT_GET_TRAN_SETTINGS: 988212420Sken { 989212420Sken struct ccb_trans_settings *cts; 990212420Sken struct ccb_trans_settings_sas *sas; 991212420Sken struct ccb_trans_settings_scsi *scsi; 992212420Sken struct mpssas_target *targ; 993212420Sken 994212420Sken cts = &ccb->cts; 995212420Sken sas = &cts->xport_specific.sas; 996212420Sken scsi = &cts->proto_specific.scsi; 997212420Sken 998212420Sken targ = &sassc->targets[cts->ccb_h.target_id]; 999212420Sken if (targ->handle == 0x0) { 1000237876Sken cts->ccb_h.status = CAM_SEL_TIMEOUT; 1001212420Sken break; 1002212420Sken } 1003212420Sken 1004212420Sken cts->protocol_version = SCSI_REV_SPC2; 1005212420Sken cts->transport = XPORT_SAS; 1006212420Sken cts->transport_version = 0; 1007212420Sken 1008212420Sken sas->valid = CTS_SAS_VALID_SPEED; 1009212420Sken switch (targ->linkrate) { 1010212420Sken case 0x08: 1011212420Sken sas->bitrate = 150000; 1012212420Sken break; 1013212420Sken case 0x09: 1014212420Sken sas->bitrate = 300000; 1015212420Sken break; 1016212420Sken case 0x0a: 1017212420Sken sas->bitrate = 600000; 1018212420Sken break; 1019212420Sken default: 1020212420Sken sas->valid = 0; 1021212420Sken } 1022212420Sken 1023212420Sken cts->protocol = PROTO_SCSI; 1024212420Sken scsi->valid = CTS_SCSI_VALID_TQ; 1025212420Sken scsi->flags = CTS_SCSI_FLAGS_TAG_ENB; 1026212420Sken 1027212420Sken cts->ccb_h.status = CAM_REQ_CMP; 1028212420Sken break; 1029212420Sken } 1030212420Sken case XPT_CALC_GEOMETRY: 1031212420Sken cam_calc_geometry(&ccb->ccg, /*extended*/1); 1032212420Sken ccb->ccb_h.status = CAM_REQ_CMP; 1033212420Sken break; 1034212420Sken case XPT_RESET_DEV: 1035254938Sken mps_dprint(sassc->sc, MPS_XINFO, "mpssas_action XPT_RESET_DEV\n"); 1036212420Sken mpssas_action_resetdev(sassc, ccb); 1037212420Sken return; 1038212420Sken case XPT_RESET_BUS: 1039212420Sken case XPT_ABORT: 1040212420Sken case XPT_TERM_IO: 1041254938Sken mps_dprint(sassc->sc, MPS_XINFO, 1042254938Sken "mpssas_action faking success for abort or reset\n"); 1043212420Sken ccb->ccb_h.status = CAM_REQ_CMP; 1044212420Sken break; 1045212420Sken case XPT_SCSI_IO: 1046212420Sken mpssas_action_scsiio(sassc, ccb); 1047212420Sken return; 1048216088Sken#if __FreeBSD_version >= 900026 1049216088Sken case XPT_SMP_IO: 1050216088Sken mpssas_action_smpio(sassc, ccb); 1051216088Sken return; 1052230920Sken#endif 1053212420Sken default: 1054212420Sken ccb->ccb_h.status = CAM_FUNC_NOTAVAIL; 1055212420Sken break; 1056212420Sken } 1057212420Sken xpt_done(ccb); 1058212420Sken 1059212420Sken} 1060212420Sken 1061212420Skenstatic void 1062230920Skenmpssas_announce_reset(struct mps_softc *sc, uint32_t ac_code, 1063230920Sken target_id_t target_id, lun_id_t lun_id) 1064212420Sken{ 1065230920Sken path_id_t path_id = cam_sim_path(sc->sassc->sim); 1066230920Sken struct cam_path *path; 1067212420Sken 1068254938Sken mps_dprint(sc, MPS_XINFO, "%s code %x target %d lun %d\n", __func__, 1069230920Sken ac_code, target_id, lun_id); 1070212420Sken 1071230920Sken if (xpt_create_path(&path, NULL, 1072230920Sken path_id, target_id, lun_id) != CAM_REQ_CMP) { 1073254938Sken mps_dprint(sc, MPS_ERROR, "unable to create path for reset " 1074230920Sken "notification\n"); 1075230920Sken return; 1076212420Sken } 1077212420Sken 1078230920Sken xpt_async(ac_code, path, NULL); 1079230920Sken xpt_free_path(path); 1080212420Sken} 1081212420Sken 1082230920Skenstatic void 1083230920Skenmpssas_complete_all_commands(struct mps_softc *sc) 1084212420Sken{ 1085212420Sken struct mps_command *cm; 1086230920Sken int i; 1087230920Sken int completed; 1088212420Sken 1089254938Sken MPS_FUNCTRACE(sc); 1090230920Sken mtx_assert(&sc->mps_mtx, MA_OWNED); 1091212420Sken 1092230920Sken /* complete all commands with a NULL reply */ 1093230920Sken for (i = 1; i < sc->num_reqs; i++) { 1094230920Sken cm = &sc->commands[i]; 1095230920Sken cm->cm_reply = NULL; 1096230920Sken completed = 0; 1097230920Sken 1098230920Sken if (cm->cm_flags & MPS_CM_FLAGS_POLLED) 1099230920Sken cm->cm_flags |= MPS_CM_FLAGS_COMPLETE; 1100230920Sken 1101230920Sken if (cm->cm_complete != NULL) { 1102254938Sken mpssas_log_command(cm, MPS_RECOVERY, 1103230920Sken "completing cm %p state %x ccb %p for diag reset\n", 1104230920Sken cm, cm->cm_state, cm->cm_ccb); 1105230920Sken 1106230920Sken cm->cm_complete(sc, cm); 1107230920Sken completed = 1; 1108230920Sken } 1109230920Sken 1110230920Sken if (cm->cm_flags & MPS_CM_FLAGS_WAKEUP) { 1111254938Sken mpssas_log_command(cm, MPS_RECOVERY, 1112230920Sken "waking up cm %p state %x ccb %p for diag reset\n", 1113230920Sken cm, cm->cm_state, cm->cm_ccb); 1114230920Sken wakeup(cm); 1115230920Sken completed = 1; 1116230920Sken } 1117230920Sken 1118230920Sken if ((completed == 0) && (cm->cm_state != MPS_CM_STATE_FREE)) { 1119230920Sken /* this should never happen, but if it does, log */ 1120254938Sken mpssas_log_command(cm, MPS_RECOVERY, 1121230920Sken "cm %p state %x flags 0x%x ccb %p during diag " 1122230920Sken "reset\n", cm, cm->cm_state, cm->cm_flags, 1123230920Sken cm->cm_ccb); 1124230920Sken } 1125212420Sken } 1126230920Sken} 1127212420Sken 1128230920Skenvoid 1129230920Skenmpssas_handle_reinit(struct mps_softc *sc) 1130230920Sken{ 1131230920Sken int i; 1132212420Sken 1133230920Sken /* Go back into startup mode and freeze the simq, so that CAM 1134230920Sken * doesn't send any commands until after we've rediscovered all 1135230920Sken * targets and found the proper device handles for them. 1136230920Sken * 1137230920Sken * After the reset, portenable will trigger discovery, and after all 1138230920Sken * discovery-related activities have finished, the simq will be 1139230920Sken * released. 1140212802Sken */ 1141254938Sken mps_dprint(sc, MPS_INIT, "%s startup\n", __func__); 1142230920Sken sc->sassc->flags |= MPSSAS_IN_STARTUP; 1143230920Sken sc->sassc->flags |= MPSSAS_IN_DISCOVERY; 1144262857Smav mpssas_startup_increment(sc->sassc); 1145212420Sken 1146230920Sken /* notify CAM of a bus reset */ 1147230920Sken mpssas_announce_reset(sc, AC_BUS_RESET, CAM_TARGET_WILDCARD, 1148230920Sken CAM_LUN_WILDCARD); 1149212420Sken 1150230920Sken /* complete and cleanup after all outstanding commands */ 1151230920Sken mpssas_complete_all_commands(sc); 1152230920Sken 1153254938Sken mps_dprint(sc, MPS_INIT, 1154254938Sken "%s startup %u tm %u after command completion\n", 1155230920Sken __func__, sc->sassc->startup_refcount, sc->sassc->tm_count); 1156230920Sken 1157230920Sken /* zero all the target handles, since they may change after the 1158230920Sken * reset, and we have to rediscover all the targets and use the new 1159230920Sken * handles. 1160230920Sken */ 1161230920Sken for (i = 0; i < sc->facts->MaxTargets; i++) { 1162230920Sken if (sc->sassc->targets[i].outstanding != 0) 1163254938Sken mps_dprint(sc, MPS_INIT, "target %u outstanding %u\n", 1164230920Sken i, sc->sassc->targets[i].outstanding); 1165230920Sken sc->sassc->targets[i].handle = 0x0; 1166230920Sken sc->sassc->targets[i].exp_dev_handle = 0x0; 1167230920Sken sc->sassc->targets[i].outstanding = 0; 1168230920Sken sc->sassc->targets[i].flags = MPSSAS_TARGET_INDIAGRESET; 1169230920Sken } 1170212420Sken} 1171254938Sken 1172230920Skenstatic void 1173230920Skenmpssas_tm_timeout(void *data) 1174230920Sken{ 1175230920Sken struct mps_command *tm = data; 1176230920Sken struct mps_softc *sc = tm->cm_sc; 1177212420Sken 1178230920Sken mtx_assert(&sc->mps_mtx, MA_OWNED); 1179230920Sken 1180254938Sken mpssas_log_command(tm, MPS_INFO|MPS_RECOVERY, 1181254938Sken "task mgmt %p timed out\n", tm); 1182230920Sken mps_reinit(sc); 1183230920Sken} 1184230920Sken 1185212420Skenstatic void 1186230920Skenmpssas_logical_unit_reset_complete(struct mps_softc *sc, struct mps_command *tm) 1187212420Sken{ 1188230920Sken MPI2_SCSI_TASK_MANAGE_REPLY *reply; 1189212420Sken MPI2_SCSI_TASK_MANAGE_REQUEST *req; 1190230920Sken unsigned int cm_count = 0; 1191230920Sken struct mps_command *cm; 1192230920Sken struct mpssas_target *targ; 1193212420Sken 1194230920Sken callout_stop(&tm->cm_callout); 1195212420Sken 1196230920Sken req = (MPI2_SCSI_TASK_MANAGE_REQUEST *)tm->cm_req; 1197230920Sken reply = (MPI2_SCSI_TASK_MANAGE_REPLY *)tm->cm_reply; 1198230920Sken targ = tm->cm_targ; 1199230920Sken 1200218812Sken /* 1201218812Sken * Currently there should be no way we can hit this case. It only 1202218812Sken * happens when we have a failure to allocate chain frames, and 1203218812Sken * task management commands don't have S/G lists. 1204254938Sken * XXXSL So should it be an assertion? 1205218812Sken */ 1206230920Sken if ((tm->cm_flags & MPS_CM_FLAGS_ERROR_MASK) != 0) { 1207254938Sken mps_dprint(sc, MPS_ERROR, "%s: cm_flags = %#x for LUN reset! " 1208230920Sken "This should not happen!\n", __func__, tm->cm_flags); 1209230920Sken mpssas_free_tm(sc, tm); 1210230920Sken return; 1211218812Sken } 1212218812Sken 1213230920Sken if (reply == NULL) { 1214254938Sken mpssas_log_command(tm, MPS_RECOVERY, 1215254938Sken "NULL reset reply for tm %p\n", tm); 1216230920Sken if ((sc->mps_flags & MPS_FLAGS_DIAGRESET) != 0) { 1217230920Sken /* this completion was due to a reset, just cleanup */ 1218230920Sken targ->flags &= ~MPSSAS_TARGET_INRESET; 1219230920Sken targ->tm = NULL; 1220230920Sken mpssas_free_tm(sc, tm); 1221230920Sken } 1222230920Sken else { 1223230920Sken /* we should have gotten a reply. */ 1224230920Sken mps_reinit(sc); 1225230920Sken } 1226230920Sken return; 1227230920Sken } 1228212420Sken 1229254938Sken mpssas_log_command(tm, MPS_RECOVERY, 1230230920Sken "logical unit reset status 0x%x code 0x%x count %u\n", 1231237876Sken le16toh(reply->IOCStatus), le32toh(reply->ResponseCode), 1232237876Sken le32toh(reply->TerminationCount)); 1233230920Sken 1234230920Sken /* See if there are any outstanding commands for this LUN. 1235230920Sken * This could be made more efficient by using a per-LU data 1236230920Sken * structure of some sort. 1237230920Sken */ 1238230920Sken TAILQ_FOREACH(cm, &targ->commands, cm_link) { 1239230920Sken if (cm->cm_lun == tm->cm_lun) 1240230920Sken cm_count++; 1241230920Sken } 1242230920Sken 1243230920Sken if (cm_count == 0) { 1244254938Sken mpssas_log_command(tm, MPS_RECOVERY|MPS_INFO, 1245230920Sken "logical unit %u finished recovery after reset\n", 1246230920Sken tm->cm_lun, tm); 1247230920Sken 1248230920Sken mpssas_announce_reset(sc, AC_SENT_BDR, tm->cm_targ->tid, 1249230920Sken tm->cm_lun); 1250230920Sken 1251230920Sken /* we've finished recovery for this logical unit. check and 1252230920Sken * see if some other logical unit has a timedout command 1253230920Sken * that needs to be processed. 1254230920Sken */ 1255230920Sken cm = TAILQ_FIRST(&targ->timedout_commands); 1256230920Sken if (cm) { 1257230920Sken mpssas_send_abort(sc, tm, cm); 1258230920Sken } 1259230920Sken else { 1260230920Sken targ->tm = NULL; 1261230920Sken mpssas_free_tm(sc, tm); 1262230920Sken } 1263230920Sken } 1264230920Sken else { 1265230920Sken /* if we still have commands for this LUN, the reset 1266230920Sken * effectively failed, regardless of the status reported. 1267230920Sken * Escalate to a target reset. 1268230920Sken */ 1269254938Sken mpssas_log_command(tm, MPS_RECOVERY, 1270230920Sken "logical unit reset complete for tm %p, but still have %u command(s)\n", 1271230920Sken tm, cm_count); 1272230920Sken mpssas_send_reset(sc, tm, 1273230920Sken MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET); 1274230920Sken } 1275212420Sken} 1276212420Sken 1277212420Skenstatic void 1278230920Skenmpssas_target_reset_complete(struct mps_softc *sc, struct mps_command *tm) 1279212420Sken{ 1280230920Sken MPI2_SCSI_TASK_MANAGE_REPLY *reply; 1281230920Sken MPI2_SCSI_TASK_MANAGE_REQUEST *req; 1282230920Sken struct mpssas_target *targ; 1283212420Sken 1284230920Sken callout_stop(&tm->cm_callout); 1285230920Sken 1286230920Sken req = (MPI2_SCSI_TASK_MANAGE_REQUEST *)tm->cm_req; 1287230920Sken reply = (MPI2_SCSI_TASK_MANAGE_REPLY *)tm->cm_reply; 1288230920Sken targ = tm->cm_targ; 1289230920Sken 1290230920Sken /* 1291230920Sken * Currently there should be no way we can hit this case. It only 1292230920Sken * happens when we have a failure to allocate chain frames, and 1293230920Sken * task management commands don't have S/G lists. 1294230920Sken */ 1295230920Sken if ((tm->cm_flags & MPS_CM_FLAGS_ERROR_MASK) != 0) { 1296254938Sken mps_dprint(sc, MPS_ERROR,"%s: cm_flags = %#x for target reset! " 1297230920Sken "This should not happen!\n", __func__, tm->cm_flags); 1298230920Sken mpssas_free_tm(sc, tm); 1299212420Sken return; 1300212420Sken } 1301212420Sken 1302230920Sken if (reply == NULL) { 1303254938Sken mpssas_log_command(tm, MPS_RECOVERY, 1304254938Sken "NULL reset reply for tm %p\n", tm); 1305230920Sken if ((sc->mps_flags & MPS_FLAGS_DIAGRESET) != 0) { 1306230920Sken /* this completion was due to a reset, just cleanup */ 1307230920Sken targ->flags &= ~MPSSAS_TARGET_INRESET; 1308230920Sken targ->tm = NULL; 1309230920Sken mpssas_free_tm(sc, tm); 1310230920Sken } 1311230920Sken else { 1312230920Sken /* we should have gotten a reply. */ 1313230920Sken mps_reinit(sc); 1314230920Sken } 1315230920Sken return; 1316230920Sken } 1317212420Sken 1318254938Sken mpssas_log_command(tm, MPS_RECOVERY, 1319230920Sken "target reset status 0x%x code 0x%x count %u\n", 1320237876Sken le16toh(reply->IOCStatus), le32toh(reply->ResponseCode), 1321237876Sken le32toh(reply->TerminationCount)); 1322212420Sken 1323230920Sken targ->flags &= ~MPSSAS_TARGET_INRESET; 1324212420Sken 1325230920Sken if (targ->outstanding == 0) { 1326230920Sken /* we've finished recovery for this target and all 1327230920Sken * of its logical units. 1328230920Sken */ 1329254938Sken mpssas_log_command(tm, MPS_RECOVERY|MPS_INFO, 1330230920Sken "recovery finished after target reset\n"); 1331213535Sken 1332230920Sken mpssas_announce_reset(sc, AC_SENT_BDR, tm->cm_targ->tid, 1333230920Sken CAM_LUN_WILDCARD); 1334230920Sken 1335230920Sken targ->tm = NULL; 1336230920Sken mpssas_free_tm(sc, tm); 1337230920Sken } 1338230920Sken else { 1339230920Sken /* after a target reset, if this target still has 1340230920Sken * outstanding commands, the reset effectively failed, 1341230920Sken * regardless of the status reported. escalate. 1342230920Sken */ 1343254938Sken mpssas_log_command(tm, MPS_RECOVERY, 1344230920Sken "target reset complete for tm %p, but still have %u command(s)\n", 1345230920Sken tm, targ->outstanding); 1346230920Sken mps_reinit(sc); 1347230920Sken } 1348213535Sken} 1349213535Sken 1350230920Sken#define MPS_RESET_TIMEOUT 30 1351230920Sken 1352213535Skenstatic int 1353230920Skenmpssas_send_reset(struct mps_softc *sc, struct mps_command *tm, uint8_t type) 1354213535Sken{ 1355230920Sken MPI2_SCSI_TASK_MANAGE_REQUEST *req; 1356230920Sken struct mpssas_target *target; 1357230920Sken int err; 1358213535Sken 1359230920Sken target = tm->cm_targ; 1360230920Sken if (target->handle == 0) { 1361254938Sken mps_dprint(sc, MPS_ERROR,"%s null devhandle for target_id %d\n", 1362230920Sken __func__, target->tid); 1363230920Sken return -1; 1364230920Sken } 1365213535Sken 1366230920Sken req = (MPI2_SCSI_TASK_MANAGE_REQUEST *)tm->cm_req; 1367237876Sken req->DevHandle = htole16(target->handle); 1368230920Sken req->Function = MPI2_FUNCTION_SCSI_TASK_MGMT; 1369230920Sken req->TaskType = type; 1370213535Sken 1371230920Sken if (type == MPI2_SCSITASKMGMT_TASKTYPE_LOGICAL_UNIT_RESET) { 1372230920Sken /* XXX Need to handle invalid LUNs */ 1373230920Sken MPS_SET_LUN(req->LUN, tm->cm_lun); 1374230920Sken tm->cm_targ->logical_unit_resets++; 1375254938Sken mpssas_log_command(tm, MPS_RECOVERY|MPS_INFO, 1376254938Sken "sending logical unit reset\n"); 1377230920Sken tm->cm_complete = mpssas_logical_unit_reset_complete; 1378230920Sken } 1379230920Sken else if (type == MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET) { 1380230920Sken /* Target reset method = SAS Hard Link Reset / SATA Link Reset */ 1381230920Sken req->MsgFlags = MPI2_SCSITASKMGMT_MSGFLAGS_LINK_RESET; 1382230920Sken tm->cm_targ->target_resets++; 1383230920Sken tm->cm_targ->flags |= MPSSAS_TARGET_INRESET; 1384254938Sken mpssas_log_command(tm, MPS_RECOVERY|MPS_INFO, 1385254938Sken "sending target reset\n"); 1386230920Sken tm->cm_complete = mpssas_target_reset_complete; 1387230920Sken } 1388230920Sken else { 1389254938Sken mps_dprint(sc, MPS_ERROR, "unexpected reset type 0x%x\n", type); 1390230920Sken return -1; 1391230920Sken } 1392230920Sken 1393230920Sken tm->cm_data = NULL; 1394230920Sken tm->cm_desc.HighPriority.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_HIGH_PRIORITY; 1395230920Sken tm->cm_complete_data = (void *)tm; 1396230920Sken 1397230920Sken callout_reset(&tm->cm_callout, MPS_RESET_TIMEOUT * hz, 1398230920Sken mpssas_tm_timeout, tm); 1399230920Sken 1400230920Sken err = mps_map_command(sc, tm); 1401230920Sken if (err) 1402254938Sken mpssas_log_command(tm, MPS_RECOVERY, 1403230920Sken "error %d sending reset type %u\n", 1404230920Sken err, type); 1405230920Sken 1406230920Sken return err; 1407213535Sken} 1408213535Sken 1409230920Sken 1410213535Skenstatic void 1411230920Skenmpssas_abort_complete(struct mps_softc *sc, struct mps_command *tm) 1412213535Sken{ 1413230920Sken struct mps_command *cm; 1414230920Sken MPI2_SCSI_TASK_MANAGE_REPLY *reply; 1415230920Sken MPI2_SCSI_TASK_MANAGE_REQUEST *req; 1416230920Sken struct mpssas_target *targ; 1417213535Sken 1418230920Sken callout_stop(&tm->cm_callout); 1419213535Sken 1420230920Sken req = (MPI2_SCSI_TASK_MANAGE_REQUEST *)tm->cm_req; 1421230920Sken reply = (MPI2_SCSI_TASK_MANAGE_REPLY *)tm->cm_reply; 1422230920Sken targ = tm->cm_targ; 1423213535Sken 1424212772Sken /* 1425230920Sken * Currently there should be no way we can hit this case. It only 1426230920Sken * happens when we have a failure to allocate chain frames, and 1427230920Sken * task management commands don't have S/G lists. 1428212772Sken */ 1429230920Sken if ((tm->cm_flags & MPS_CM_FLAGS_ERROR_MASK) != 0) { 1430254938Sken mpssas_log_command(tm, MPS_RECOVERY, 1431230920Sken "cm_flags = %#x for abort %p TaskMID %u!\n", 1432237876Sken tm->cm_flags, tm, le16toh(req->TaskMID)); 1433230920Sken mpssas_free_tm(sc, tm); 1434230920Sken return; 1435230920Sken } 1436212772Sken 1437230920Sken if (reply == NULL) { 1438254938Sken mpssas_log_command(tm, MPS_RECOVERY, 1439230920Sken "NULL abort reply for tm %p TaskMID %u\n", 1440237876Sken tm, le16toh(req->TaskMID)); 1441230920Sken if ((sc->mps_flags & MPS_FLAGS_DIAGRESET) != 0) { 1442230920Sken /* this completion was due to a reset, just cleanup */ 1443230920Sken targ->tm = NULL; 1444230920Sken mpssas_free_tm(sc, tm); 1445230920Sken } 1446230920Sken else { 1447230920Sken /* we should have gotten a reply. */ 1448230920Sken mps_reinit(sc); 1449230920Sken } 1450230920Sken return; 1451230920Sken } 1452212420Sken 1453254938Sken mpssas_log_command(tm, MPS_RECOVERY, 1454230920Sken "abort TaskMID %u status 0x%x code 0x%x count %u\n", 1455237876Sken le16toh(req->TaskMID), 1456237876Sken le16toh(reply->IOCStatus), le32toh(reply->ResponseCode), 1457237876Sken le32toh(reply->TerminationCount)); 1458213535Sken 1459230920Sken cm = TAILQ_FIRST(&tm->cm_targ->timedout_commands); 1460230920Sken if (cm == NULL) { 1461230920Sken /* if there are no more timedout commands, we're done with 1462230920Sken * error recovery for this target. 1463213535Sken */ 1464254938Sken mpssas_log_command(tm, MPS_RECOVERY, 1465230920Sken "finished recovery after aborting TaskMID %u\n", 1466237876Sken le16toh(req->TaskMID)); 1467230920Sken 1468230920Sken targ->tm = NULL; 1469230920Sken mpssas_free_tm(sc, tm); 1470212420Sken } 1471237876Sken else if (le16toh(req->TaskMID) != cm->cm_desc.Default.SMID) { 1472230920Sken /* abort success, but we have more timedout commands to abort */ 1473254938Sken mpssas_log_command(tm, MPS_RECOVERY, 1474230920Sken "continuing recovery after aborting TaskMID %u\n", 1475237876Sken le16toh(req->TaskMID)); 1476230920Sken 1477230920Sken mpssas_send_abort(sc, tm, cm); 1478230920Sken } 1479230920Sken else { 1480230920Sken /* we didn't get a command completion, so the abort 1481230920Sken * failed as far as we're concerned. escalate. 1482230920Sken */ 1483254938Sken mpssas_log_command(tm, MPS_RECOVERY, 1484230920Sken "abort failed for TaskMID %u tm %p\n", 1485237876Sken le16toh(req->TaskMID), tm); 1486230920Sken 1487230920Sken mpssas_send_reset(sc, tm, 1488230920Sken MPI2_SCSITASKMGMT_TASKTYPE_LOGICAL_UNIT_RESET); 1489230920Sken } 1490213535Sken} 1491212420Sken 1492230920Sken#define MPS_ABORT_TIMEOUT 5 1493230920Sken 1494230920Skenstatic int 1495230920Skenmpssas_send_abort(struct mps_softc *sc, struct mps_command *tm, struct mps_command *cm) 1496213535Sken{ 1497230920Sken MPI2_SCSI_TASK_MANAGE_REQUEST *req; 1498230920Sken struct mpssas_target *targ; 1499230920Sken int err; 1500212420Sken 1501230920Sken targ = cm->cm_targ; 1502230920Sken if (targ->handle == 0) { 1503254938Sken mps_dprint(sc, MPS_ERROR,"%s null devhandle for target_id %d\n", 1504230920Sken __func__, cm->cm_ccb->ccb_h.target_id); 1505230920Sken return -1; 1506230920Sken } 1507213535Sken 1508254938Sken mpssas_log_command(tm, MPS_RECOVERY|MPS_INFO, 1509254938Sken "Aborting command %p\n", cm); 1510254938Sken 1511230920Sken req = (MPI2_SCSI_TASK_MANAGE_REQUEST *)tm->cm_req; 1512237876Sken req->DevHandle = htole16(targ->handle); 1513230920Sken req->Function = MPI2_FUNCTION_SCSI_TASK_MGMT; 1514230920Sken req->TaskType = MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK; 1515213535Sken 1516230920Sken /* XXX Need to handle invalid LUNs */ 1517230920Sken MPS_SET_LUN(req->LUN, cm->cm_ccb->ccb_h.target_lun); 1518212420Sken 1519237876Sken req->TaskMID = htole16(cm->cm_desc.Default.SMID); 1520213535Sken 1521230920Sken tm->cm_data = NULL; 1522230920Sken tm->cm_desc.HighPriority.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_HIGH_PRIORITY; 1523230920Sken tm->cm_complete = mpssas_abort_complete; 1524230920Sken tm->cm_complete_data = (void *)tm; 1525230920Sken tm->cm_targ = cm->cm_targ; 1526230920Sken tm->cm_lun = cm->cm_lun; 1527213535Sken 1528230920Sken callout_reset(&tm->cm_callout, MPS_ABORT_TIMEOUT * hz, 1529230920Sken mpssas_tm_timeout, tm); 1530213535Sken 1531230920Sken targ->aborts++; 1532213535Sken 1533230920Sken err = mps_map_command(sc, tm); 1534230920Sken if (err) 1535254938Sken mpssas_log_command(tm, MPS_RECOVERY, 1536230920Sken "error %d sending abort for cm %p SMID %u\n", 1537230920Sken err, cm, req->TaskMID); 1538230920Sken return err; 1539230920Sken} 1540213535Sken 1541213535Sken 1542230920Skenstatic void 1543230920Skenmpssas_scsiio_timeout(void *data) 1544230920Sken{ 1545230920Sken struct mps_softc *sc; 1546230920Sken struct mps_command *cm; 1547230920Sken struct mpssas_target *targ; 1548213535Sken 1549230920Sken cm = (struct mps_command *)data; 1550230920Sken sc = cm->cm_sc; 1551213535Sken 1552254938Sken MPS_FUNCTRACE(sc); 1553230920Sken mtx_assert(&sc->mps_mtx, MA_OWNED); 1554213535Sken 1555254938Sken mps_dprint(sc, MPS_XINFO, "Timeout checking cm %p\n", sc); 1556213535Sken 1557230920Sken /* 1558230920Sken * Run the interrupt handler to make sure it's not pending. This 1559230920Sken * isn't perfect because the command could have already completed 1560230920Sken * and been re-used, though this is unlikely. 1561230920Sken */ 1562230920Sken mps_intr_locked(sc); 1563230920Sken if (cm->cm_state == MPS_CM_STATE_FREE) { 1564254938Sken mpssas_log_command(cm, MPS_XINFO, 1565254938Sken "SCSI command %p almost timed out\n", cm); 1566230920Sken return; 1567230920Sken } 1568213535Sken 1569230920Sken if (cm->cm_ccb == NULL) { 1570254938Sken mps_dprint(sc, MPS_ERROR, "command timeout with NULL ccb\n"); 1571230920Sken return; 1572230920Sken } 1573213535Sken 1574254938Sken mpssas_log_command(cm, MPS_INFO, "command timeout cm %p ccb %p\n", 1575230920Sken cm, cm->cm_ccb); 1576213535Sken 1577230920Sken targ = cm->cm_targ; 1578230920Sken targ->timeouts++; 1579213535Sken 1580230920Sken /* XXX first, check the firmware state, to see if it's still 1581230920Sken * operational. if not, do a diag reset. 1582230920Sken */ 1583230920Sken 1584230920Sken cm->cm_ccb->ccb_h.status = CAM_CMD_TIMEOUT; 1585230920Sken cm->cm_state = MPS_CM_STATE_TIMEDOUT; 1586230920Sken TAILQ_INSERT_TAIL(&targ->timedout_commands, cm, cm_recovery); 1587230920Sken 1588230920Sken if (targ->tm != NULL) { 1589230920Sken /* target already in recovery, just queue up another 1590230920Sken * timedout command to be processed later. 1591230920Sken */ 1592254938Sken mps_dprint(sc, MPS_RECOVERY, 1593254938Sken "queued timedout cm %p for processing by tm %p\n", 1594230920Sken cm, targ->tm); 1595213535Sken } 1596230920Sken else if ((targ->tm = mpssas_alloc_tm(sc)) != NULL) { 1597254938Sken mps_dprint(sc, MPS_RECOVERY, "timedout cm %p allocated tm %p\n", 1598230920Sken cm, targ->tm); 1599213535Sken 1600230920Sken /* start recovery by aborting the first timedout command */ 1601230920Sken mpssas_send_abort(sc, targ->tm, cm); 1602230920Sken } 1603230920Sken else { 1604230920Sken /* XXX queue this target up for recovery once a TM becomes 1605230920Sken * available. The firmware only has a limited number of 1606230920Sken * HighPriority credits for the high priority requests used 1607230920Sken * for task management, and we ran out. 1608230920Sken * 1609230920Sken * Isilon: don't worry about this for now, since we have 1610230920Sken * more credits than disks in an enclosure, and limit 1611230920Sken * ourselves to one TM per target for recovery. 1612230920Sken */ 1613254938Sken mps_dprint(sc, MPS_RECOVERY, 1614254938Sken "timedout cm %p failed to allocate a tm\n", cm); 1615230920Sken } 1616230920Sken 1617213535Sken} 1618213535Sken 1619212420Skenstatic void 1620212420Skenmpssas_action_scsiio(struct mpssas_softc *sassc, union ccb *ccb) 1621212420Sken{ 1622212420Sken MPI2_SCSI_IO_REQUEST *req; 1623212420Sken struct ccb_scsiio *csio; 1624212420Sken struct mps_softc *sc; 1625212420Sken struct mpssas_target *targ; 1626230920Sken struct mpssas_lun *lun; 1627212420Sken struct mps_command *cm; 1628230920Sken uint8_t i, lba_byte, *ref_tag_addr; 1629230920Sken uint16_t eedp_flags; 1630237876Sken uint32_t mpi_control; 1631212420Sken 1632212420Sken sc = sassc->sc; 1633254938Sken MPS_FUNCTRACE(sc); 1634230920Sken mtx_assert(&sc->mps_mtx, MA_OWNED); 1635212420Sken 1636212420Sken csio = &ccb->csio; 1637212420Sken targ = &sassc->targets[csio->ccb_h.target_id]; 1638254938Sken mps_dprint(sc, MPS_TRACE, "ccb %p target flag %x\n", ccb, targ->flags); 1639212420Sken if (targ->handle == 0x0) { 1640254938Sken mps_dprint(sc, MPS_ERROR, "%s NULL handle for target %u\n", 1641230920Sken __func__, csio->ccb_h.target_id); 1642237876Sken csio->ccb_h.status = CAM_SEL_TIMEOUT; 1643212420Sken xpt_done(ccb); 1644212420Sken return; 1645212420Sken } 1646231679Sken if (targ->flags & MPS_TARGET_FLAGS_RAID_COMPONENT) { 1647254938Sken mps_dprint(sc, MPS_ERROR, "%s Raid component no SCSI IO " 1648254938Sken "supported %u\n", __func__, csio->ccb_h.target_id); 1649231679Sken csio->ccb_h.status = CAM_TID_INVALID; 1650231679Sken xpt_done(ccb); 1651231679Sken return; 1652231679Sken } 1653230920Sken /* 1654254938Sken * Sometimes, it is possible to get a command that is not "In 1655254938Sken * Progress" and was actually aborted by the upper layer. Check for 1656254938Sken * this here and complete the command without error. 1657254938Sken */ 1658254938Sken if (ccb->ccb_h.status != CAM_REQ_INPROG) { 1659254938Sken mps_dprint(sc, MPS_TRACE, "%s Command is not in progress for " 1660254938Sken "target %u\n", __func__, csio->ccb_h.target_id); 1661254938Sken xpt_done(ccb); 1662254938Sken return; 1663254938Sken } 1664254938Sken /* 1665230920Sken * If devinfo is 0 this will be a volume. In that case don't tell CAM 1666230920Sken * that the volume has timed out. We want volumes to be enumerated 1667230920Sken * until they are deleted/removed, not just failed. 1668230920Sken */ 1669230920Sken if (targ->flags & MPSSAS_TARGET_INREMOVAL) { 1670230920Sken if (targ->devinfo == 0) 1671230920Sken csio->ccb_h.status = CAM_REQ_CMP; 1672230920Sken else 1673230920Sken csio->ccb_h.status = CAM_SEL_TIMEOUT; 1674230920Sken xpt_done(ccb); 1675230920Sken return; 1676230920Sken } 1677212420Sken 1678230920Sken if ((sc->mps_flags & MPS_FLAGS_SHUTDOWN) != 0) { 1679254938Sken mps_dprint(sc, MPS_INFO, "%s shutting down\n", __func__); 1680230920Sken csio->ccb_h.status = CAM_TID_INVALID; 1681230920Sken xpt_done(ccb); 1682230920Sken return; 1683230920Sken } 1684230920Sken 1685212420Sken cm = mps_alloc_command(sc); 1686212420Sken if (cm == NULL) { 1687212420Sken if ((sassc->flags & MPSSAS_QUEUE_FROZEN) == 0) { 1688212420Sken xpt_freeze_simq(sassc->sim, 1); 1689212420Sken sassc->flags |= MPSSAS_QUEUE_FROZEN; 1690212420Sken } 1691212420Sken ccb->ccb_h.status &= ~CAM_SIM_QUEUED; 1692212420Sken ccb->ccb_h.status |= CAM_REQUEUE_REQ; 1693212420Sken xpt_done(ccb); 1694212420Sken return; 1695212420Sken } 1696212420Sken 1697212420Sken req = (MPI2_SCSI_IO_REQUEST *)cm->cm_req; 1698218812Sken bzero(req, sizeof(*req)); 1699237876Sken req->DevHandle = htole16(targ->handle); 1700212420Sken req->Function = MPI2_FUNCTION_SCSI_IO_REQUEST; 1701212420Sken req->MsgFlags = 0; 1702237876Sken req->SenseBufferLowAddress = htole32(cm->cm_sense_busaddr); 1703212420Sken req->SenseBufferLength = MPS_SENSE_LEN; 1704212420Sken req->SGLFlags = 0; 1705212420Sken req->ChainOffset = 0; 1706212420Sken req->SGLOffset0 = 24; /* 32bit word offset to the SGL */ 1707212420Sken req->SGLOffset1= 0; 1708212420Sken req->SGLOffset2= 0; 1709212420Sken req->SGLOffset3= 0; 1710212420Sken req->SkipCount = 0; 1711237876Sken req->DataLength = htole32(csio->dxfer_len); 1712212420Sken req->BidirectionalDataLength = 0; 1713237876Sken req->IoFlags = htole16(csio->cdb_len); 1714212420Sken req->EEDPFlags = 0; 1715212420Sken 1716212420Sken /* Note: BiDirectional transfers are not supported */ 1717212420Sken switch (csio->ccb_h.flags & CAM_DIR_MASK) { 1718212420Sken case CAM_DIR_IN: 1719237876Sken mpi_control = MPI2_SCSIIO_CONTROL_READ; 1720212420Sken cm->cm_flags |= MPS_CM_FLAGS_DATAIN; 1721212420Sken break; 1722212420Sken case CAM_DIR_OUT: 1723237876Sken mpi_control = MPI2_SCSIIO_CONTROL_WRITE; 1724212420Sken cm->cm_flags |= MPS_CM_FLAGS_DATAOUT; 1725212420Sken break; 1726212420Sken case CAM_DIR_NONE: 1727212420Sken default: 1728237876Sken mpi_control = MPI2_SCSIIO_CONTROL_NODATATRANSFER; 1729212420Sken break; 1730212420Sken } 1731237876Sken 1732254938Sken if (csio->cdb_len == 32) 1733237876Sken mpi_control |= 4 << MPI2_SCSIIO_CONTROL_ADDCDBLEN_SHIFT; 1734212420Sken /* 1735212420Sken * It looks like the hardware doesn't require an explicit tag 1736212420Sken * number for each transaction. SAM Task Management not supported 1737212420Sken * at the moment. 1738212420Sken */ 1739212420Sken switch (csio->tag_action) { 1740212420Sken case MSG_HEAD_OF_Q_TAG: 1741237876Sken mpi_control |= MPI2_SCSIIO_CONTROL_HEADOFQ; 1742212420Sken break; 1743212420Sken case MSG_ORDERED_Q_TAG: 1744237876Sken mpi_control |= MPI2_SCSIIO_CONTROL_ORDEREDQ; 1745212420Sken break; 1746212420Sken case MSG_ACA_TASK: 1747237876Sken mpi_control |= MPI2_SCSIIO_CONTROL_ACAQ; 1748212420Sken break; 1749212420Sken case CAM_TAG_ACTION_NONE: 1750212420Sken case MSG_SIMPLE_Q_TAG: 1751212420Sken default: 1752237876Sken mpi_control |= MPI2_SCSIIO_CONTROL_SIMPLEQ; 1753212420Sken break; 1754212420Sken } 1755237876Sken mpi_control |= sc->mapping_table[csio->ccb_h.target_id].TLR_bits; 1756237876Sken req->Control = htole32(mpi_control); 1757216368Sken if (MPS_SET_LUN(req->LUN, csio->ccb_h.target_lun) != 0) { 1758212420Sken mps_free_command(sc, cm); 1759212420Sken ccb->ccb_h.status = CAM_LUN_INVALID; 1760212420Sken xpt_done(ccb); 1761212420Sken return; 1762212420Sken } 1763212420Sken 1764212420Sken if (csio->ccb_h.flags & CAM_CDB_POINTER) 1765212420Sken bcopy(csio->cdb_io.cdb_ptr, &req->CDB.CDB32[0], csio->cdb_len); 1766212420Sken else 1767212420Sken bcopy(csio->cdb_io.cdb_bytes, &req->CDB.CDB32[0],csio->cdb_len); 1768237876Sken req->IoFlags = htole16(csio->cdb_len); 1769212420Sken 1770216088Sken /* 1771230920Sken * Check if EEDP is supported and enabled. If it is then check if the 1772230920Sken * SCSI opcode could be using EEDP. If so, make sure the LUN exists and 1773230920Sken * is formatted for EEDP support. If all of this is true, set CDB up 1774230920Sken * for EEDP transfer. 1775216088Sken */ 1776230920Sken eedp_flags = op_code_prot[req->CDB.CDB32[0]]; 1777230920Sken if (sc->eedp_enabled && eedp_flags) { 1778230920Sken SLIST_FOREACH(lun, &targ->luns, lun_link) { 1779230920Sken if (lun->lun_id == csio->ccb_h.target_lun) { 1780230920Sken break; 1781230920Sken } 1782230920Sken } 1783230920Sken 1784230920Sken if ((lun != NULL) && (lun->eedp_formatted)) { 1785237876Sken req->EEDPBlockSize = htole16(lun->eedp_block_size); 1786230920Sken eedp_flags |= (MPI2_SCSIIO_EEDPFLAGS_INC_PRI_REFTAG | 1787230920Sken MPI2_SCSIIO_EEDPFLAGS_CHECK_REFTAG | 1788230920Sken MPI2_SCSIIO_EEDPFLAGS_CHECK_GUARD); 1789237876Sken req->EEDPFlags = htole16(eedp_flags); 1790230920Sken 1791230920Sken /* 1792230920Sken * If CDB less than 32, fill in Primary Ref Tag with 1793230920Sken * low 4 bytes of LBA. If CDB is 32, tag stuff is 1794230920Sken * already there. Also, set protection bit. FreeBSD 1795230920Sken * currently does not support CDBs bigger than 16, but 1796230920Sken * the code doesn't hurt, and will be here for the 1797230920Sken * future. 1798230920Sken */ 1799230920Sken if (csio->cdb_len != 32) { 1800230920Sken lba_byte = (csio->cdb_len == 16) ? 6 : 2; 1801230920Sken ref_tag_addr = (uint8_t *)&req->CDB.EEDP32. 1802230920Sken PrimaryReferenceTag; 1803230920Sken for (i = 0; i < 4; i++) { 1804230920Sken *ref_tag_addr = 1805230920Sken req->CDB.CDB32[lba_byte + i]; 1806230920Sken ref_tag_addr++; 1807230920Sken } 1808237876Sken req->CDB.EEDP32.PrimaryReferenceTag = 1809237876Sken htole32(req->CDB.EEDP32.PrimaryReferenceTag); 1810230920Sken req->CDB.EEDP32.PrimaryApplicationTagMask = 1811230920Sken 0xFFFF; 1812230920Sken req->CDB.CDB32[1] = (req->CDB.CDB32[1] & 0x1F) | 1813230920Sken 0x20; 1814230920Sken } else { 1815230920Sken eedp_flags |= 1816230920Sken MPI2_SCSIIO_EEDPFLAGS_INC_PRI_APPTAG; 1817237876Sken req->EEDPFlags = htole16(eedp_flags); 1818230920Sken req->CDB.CDB32[10] = (req->CDB.CDB32[10] & 1819230920Sken 0x1F) | 0x20; 1820230920Sken } 1821230920Sken } 1822230920Sken } 1823230920Sken 1824212420Sken cm->cm_length = csio->dxfer_len; 1825251874Sscottl if (cm->cm_length != 0) { 1826251874Sscottl cm->cm_data = ccb; 1827251874Sscottl cm->cm_flags |= MPS_CM_FLAGS_USE_CCB; 1828251874Sscottl } else { 1829251874Sscottl cm->cm_data = NULL; 1830251874Sscottl } 1831212420Sken cm->cm_sge = &req->SGL; 1832212420Sken cm->cm_sglsize = (32 - 24) * 4; 1833212420Sken cm->cm_desc.SCSIIO.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_SCSI_IO; 1834237876Sken cm->cm_desc.SCSIIO.DevHandle = htole16(targ->handle); 1835212420Sken cm->cm_complete = mpssas_scsiio_complete; 1836212420Sken cm->cm_complete_data = ccb; 1837212420Sken cm->cm_targ = targ; 1838230920Sken cm->cm_lun = csio->ccb_h.target_lun; 1839230920Sken cm->cm_ccb = ccb; 1840212420Sken 1841230920Sken /* 1842230920Sken * If HBA is a WD and the command is not for a retry, try to build a 1843230920Sken * direct I/O message. If failed, or the command is for a retry, send 1844230920Sken * the I/O to the IR volume itself. 1845230920Sken */ 1846230920Sken if (sc->WD_valid_config) { 1847230920Sken if (ccb->ccb_h.status != MPS_WD_RETRY) { 1848230920Sken mpssas_direct_drive_io(sassc, cm, ccb); 1849230920Sken } else { 1850230920Sken ccb->ccb_h.status = CAM_REQ_INPROG; 1851230920Sken } 1852230920Sken } 1853218812Sken 1854212420Sken callout_reset(&cm->cm_callout, (ccb->ccb_h.timeout * hz) / 1000, 1855212420Sken mpssas_scsiio_timeout, cm); 1856212420Sken 1857230920Sken targ->issued++; 1858230920Sken targ->outstanding++; 1859230920Sken TAILQ_INSERT_TAIL(&targ->commands, cm, cm_link); 1860254938Sken ccb->ccb_h.status |= CAM_SIM_QUEUED; 1861230920Sken 1862254938Sken mpssas_log_command(cm, MPS_XINFO, "%s cm %p ccb %p outstanding %u\n", 1863254938Sken __func__, cm, ccb, targ->outstanding); 1864230920Sken 1865212420Sken mps_map_command(sc, cm); 1866212420Sken return; 1867212420Sken} 1868212420Sken 1869212420Skenstatic void 1870231679Skenmps_response_code(struct mps_softc *sc, u8 response_code) 1871231679Sken{ 1872231679Sken char *desc; 1873231679Sken 1874231679Sken switch (response_code) { 1875231679Sken case MPI2_SCSITASKMGMT_RSP_TM_COMPLETE: 1876231679Sken desc = "task management request completed"; 1877231679Sken break; 1878231679Sken case MPI2_SCSITASKMGMT_RSP_INVALID_FRAME: 1879231679Sken desc = "invalid frame"; 1880231679Sken break; 1881231679Sken case MPI2_SCSITASKMGMT_RSP_TM_NOT_SUPPORTED: 1882231679Sken desc = "task management request not supported"; 1883231679Sken break; 1884231679Sken case MPI2_SCSITASKMGMT_RSP_TM_FAILED: 1885231679Sken desc = "task management request failed"; 1886231679Sken break; 1887231679Sken case MPI2_SCSITASKMGMT_RSP_TM_SUCCEEDED: 1888231679Sken desc = "task management request succeeded"; 1889231679Sken break; 1890231679Sken case MPI2_SCSITASKMGMT_RSP_TM_INVALID_LUN: 1891231679Sken desc = "invalid lun"; 1892231679Sken break; 1893231679Sken case 0xA: 1894231679Sken desc = "overlapped tag attempted"; 1895231679Sken break; 1896231679Sken case MPI2_SCSITASKMGMT_RSP_IO_QUEUED_ON_IOC: 1897231679Sken desc = "task queued, however not sent to target"; 1898231679Sken break; 1899231679Sken default: 1900231679Sken desc = "unknown"; 1901231679Sken break; 1902231679Sken } 1903254938Sken mps_dprint(sc, MPS_XINFO, "response_code(0x%01x): %s\n", 1904231679Sken response_code, desc); 1905231679Sken} 1906231679Sken/** 1907231679Sken * mps_sc_failed_io_info - translated non-succesfull SCSI_IO request 1908231679Sken */ 1909231679Skenstatic void 1910231679Skenmps_sc_failed_io_info(struct mps_softc *sc, struct ccb_scsiio *csio, 1911231679Sken Mpi2SCSIIOReply_t *mpi_reply) 1912231679Sken{ 1913231679Sken u32 response_info; 1914231679Sken u8 *response_bytes; 1915231679Sken u16 ioc_status = le16toh(mpi_reply->IOCStatus) & 1916231679Sken MPI2_IOCSTATUS_MASK; 1917231679Sken u8 scsi_state = mpi_reply->SCSIState; 1918231679Sken u8 scsi_status = mpi_reply->SCSIStatus; 1919231679Sken char *desc_ioc_state = NULL; 1920231679Sken char *desc_scsi_status = NULL; 1921231679Sken char *desc_scsi_state = sc->tmp_string; 1922231679Sken u32 log_info = le32toh(mpi_reply->IOCLogInfo); 1923231679Sken 1924231679Sken if (log_info == 0x31170000) 1925231679Sken return; 1926231679Sken 1927231679Sken switch (ioc_status) { 1928231679Sken case MPI2_IOCSTATUS_SUCCESS: 1929231679Sken desc_ioc_state = "success"; 1930231679Sken break; 1931231679Sken case MPI2_IOCSTATUS_INVALID_FUNCTION: 1932231679Sken desc_ioc_state = "invalid function"; 1933231679Sken break; 1934231679Sken case MPI2_IOCSTATUS_SCSI_RECOVERED_ERROR: 1935231679Sken desc_ioc_state = "scsi recovered error"; 1936231679Sken break; 1937231679Sken case MPI2_IOCSTATUS_SCSI_INVALID_DEVHANDLE: 1938231679Sken desc_ioc_state = "scsi invalid dev handle"; 1939231679Sken break; 1940231679Sken case MPI2_IOCSTATUS_SCSI_DEVICE_NOT_THERE: 1941231679Sken desc_ioc_state = "scsi device not there"; 1942231679Sken break; 1943231679Sken case MPI2_IOCSTATUS_SCSI_DATA_OVERRUN: 1944231679Sken desc_ioc_state = "scsi data overrun"; 1945231679Sken break; 1946231679Sken case MPI2_IOCSTATUS_SCSI_DATA_UNDERRUN: 1947231679Sken desc_ioc_state = "scsi data underrun"; 1948231679Sken break; 1949231679Sken case MPI2_IOCSTATUS_SCSI_IO_DATA_ERROR: 1950231679Sken desc_ioc_state = "scsi io data error"; 1951231679Sken break; 1952231679Sken case MPI2_IOCSTATUS_SCSI_PROTOCOL_ERROR: 1953231679Sken desc_ioc_state = "scsi protocol error"; 1954231679Sken break; 1955231679Sken case MPI2_IOCSTATUS_SCSI_TASK_TERMINATED: 1956231679Sken desc_ioc_state = "scsi task terminated"; 1957231679Sken break; 1958231679Sken case MPI2_IOCSTATUS_SCSI_RESIDUAL_MISMATCH: 1959231679Sken desc_ioc_state = "scsi residual mismatch"; 1960231679Sken break; 1961231679Sken case MPI2_IOCSTATUS_SCSI_TASK_MGMT_FAILED: 1962231679Sken desc_ioc_state = "scsi task mgmt failed"; 1963231679Sken break; 1964231679Sken case MPI2_IOCSTATUS_SCSI_IOC_TERMINATED: 1965231679Sken desc_ioc_state = "scsi ioc terminated"; 1966231679Sken break; 1967231679Sken case MPI2_IOCSTATUS_SCSI_EXT_TERMINATED: 1968231679Sken desc_ioc_state = "scsi ext terminated"; 1969231679Sken break; 1970231679Sken case MPI2_IOCSTATUS_EEDP_GUARD_ERROR: 1971231679Sken desc_ioc_state = "eedp guard error"; 1972231679Sken break; 1973231679Sken case MPI2_IOCSTATUS_EEDP_REF_TAG_ERROR: 1974231679Sken desc_ioc_state = "eedp ref tag error"; 1975231679Sken break; 1976231679Sken case MPI2_IOCSTATUS_EEDP_APP_TAG_ERROR: 1977231679Sken desc_ioc_state = "eedp app tag error"; 1978231679Sken break; 1979231679Sken default: 1980231679Sken desc_ioc_state = "unknown"; 1981231679Sken break; 1982231679Sken } 1983231679Sken 1984231679Sken switch (scsi_status) { 1985231679Sken case MPI2_SCSI_STATUS_GOOD: 1986231679Sken desc_scsi_status = "good"; 1987231679Sken break; 1988231679Sken case MPI2_SCSI_STATUS_CHECK_CONDITION: 1989231679Sken desc_scsi_status = "check condition"; 1990231679Sken break; 1991231679Sken case MPI2_SCSI_STATUS_CONDITION_MET: 1992231679Sken desc_scsi_status = "condition met"; 1993231679Sken break; 1994231679Sken case MPI2_SCSI_STATUS_BUSY: 1995231679Sken desc_scsi_status = "busy"; 1996231679Sken break; 1997231679Sken case MPI2_SCSI_STATUS_INTERMEDIATE: 1998231679Sken desc_scsi_status = "intermediate"; 1999231679Sken break; 2000231679Sken case MPI2_SCSI_STATUS_INTERMEDIATE_CONDMET: 2001231679Sken desc_scsi_status = "intermediate condmet"; 2002231679Sken break; 2003231679Sken case MPI2_SCSI_STATUS_RESERVATION_CONFLICT: 2004231679Sken desc_scsi_status = "reservation conflict"; 2005231679Sken break; 2006231679Sken case MPI2_SCSI_STATUS_COMMAND_TERMINATED: 2007231679Sken desc_scsi_status = "command terminated"; 2008231679Sken break; 2009231679Sken case MPI2_SCSI_STATUS_TASK_SET_FULL: 2010231679Sken desc_scsi_status = "task set full"; 2011231679Sken break; 2012231679Sken case MPI2_SCSI_STATUS_ACA_ACTIVE: 2013231679Sken desc_scsi_status = "aca active"; 2014231679Sken break; 2015231679Sken case MPI2_SCSI_STATUS_TASK_ABORTED: 2016231679Sken desc_scsi_status = "task aborted"; 2017231679Sken break; 2018231679Sken default: 2019231679Sken desc_scsi_status = "unknown"; 2020231679Sken break; 2021231679Sken } 2022231679Sken 2023231679Sken desc_scsi_state[0] = '\0'; 2024231679Sken if (!scsi_state) 2025231679Sken desc_scsi_state = " "; 2026231679Sken if (scsi_state & MPI2_SCSI_STATE_RESPONSE_INFO_VALID) 2027231679Sken strcat(desc_scsi_state, "response info "); 2028231679Sken if (scsi_state & MPI2_SCSI_STATE_TERMINATED) 2029231679Sken strcat(desc_scsi_state, "state terminated "); 2030231679Sken if (scsi_state & MPI2_SCSI_STATE_NO_SCSI_STATUS) 2031231679Sken strcat(desc_scsi_state, "no status "); 2032231679Sken if (scsi_state & MPI2_SCSI_STATE_AUTOSENSE_FAILED) 2033231679Sken strcat(desc_scsi_state, "autosense failed "); 2034231679Sken if (scsi_state & MPI2_SCSI_STATE_AUTOSENSE_VALID) 2035231679Sken strcat(desc_scsi_state, "autosense valid "); 2036231679Sken 2037254938Sken mps_dprint(sc, MPS_XINFO, "\thandle(0x%04x), ioc_status(%s)(0x%04x)\n", 2038254938Sken le16toh(mpi_reply->DevHandle), desc_ioc_state, ioc_status); 2039231679Sken /* We can add more detail about underflow data here 2040231679Sken * TO-DO 2041231679Sken * */ 2042254938Sken mps_dprint(sc, MPS_XINFO, "\tscsi_status(%s)(0x%02x), " 2043254938Sken "scsi_state(%s)(0x%02x)\n", desc_scsi_status, scsi_status, 2044254938Sken desc_scsi_state, scsi_state); 2045231679Sken 2046254938Sken if (sc->mps_debug & MPS_XINFO && 2047231679Sken scsi_state & MPI2_SCSI_STATE_AUTOSENSE_VALID) { 2048254938Sken mps_dprint(sc, MPS_XINFO, "-> Sense Buffer Data : Start :\n"); 2049231679Sken scsi_sense_print(csio); 2050254938Sken mps_dprint(sc, MPS_XINFO, "-> Sense Buffer Data : End :\n"); 2051231679Sken } 2052231679Sken 2053231679Sken if (scsi_state & MPI2_SCSI_STATE_RESPONSE_INFO_VALID) { 2054231679Sken response_info = le32toh(mpi_reply->ResponseInfo); 2055231679Sken response_bytes = (u8 *)&response_info; 2056231679Sken mps_response_code(sc,response_bytes[0]); 2057231679Sken } 2058231679Sken} 2059231679Sken 2060231679Skenstatic void 2061212420Skenmpssas_scsiio_complete(struct mps_softc *sc, struct mps_command *cm) 2062212420Sken{ 2063212420Sken MPI2_SCSI_IO_REPLY *rep; 2064212420Sken union ccb *ccb; 2065230920Sken struct ccb_scsiio *csio; 2066212420Sken struct mpssas_softc *sassc; 2067230920Sken struct scsi_vpd_supported_page_list *vpd_list = NULL; 2068230920Sken u8 *TLR_bits, TLR_on; 2069230920Sken int dir = 0, i; 2070230920Sken u16 alloc_len; 2071212420Sken 2072254938Sken MPS_FUNCTRACE(sc); 2073230920Sken mps_dprint(sc, MPS_TRACE, 2074254938Sken "cm %p SMID %u ccb %p reply %p outstanding %u\n", cm, 2075254938Sken cm->cm_desc.Default.SMID, cm->cm_ccb, cm->cm_reply, 2076230920Sken cm->cm_targ->outstanding); 2077212420Sken 2078212420Sken callout_stop(&cm->cm_callout); 2079230920Sken mtx_assert(&sc->mps_mtx, MA_OWNED); 2080212420Sken 2081212420Sken sassc = sc->sassc; 2082212420Sken ccb = cm->cm_complete_data; 2083230920Sken csio = &ccb->csio; 2084212420Sken rep = (MPI2_SCSI_IO_REPLY *)cm->cm_reply; 2085218812Sken /* 2086218812Sken * XXX KDM if the chain allocation fails, does it matter if we do 2087218812Sken * the sync and unload here? It is simpler to do it in every case, 2088218812Sken * assuming it doesn't cause problems. 2089218812Sken */ 2090212420Sken if (cm->cm_data != NULL) { 2091212420Sken if (cm->cm_flags & MPS_CM_FLAGS_DATAIN) 2092212420Sken dir = BUS_DMASYNC_POSTREAD; 2093212420Sken else if (cm->cm_flags & MPS_CM_FLAGS_DATAOUT) 2094242544Seadler dir = BUS_DMASYNC_POSTWRITE; 2095212420Sken bus_dmamap_sync(sc->buffer_dmat, cm->cm_dmamap, dir); 2096212420Sken bus_dmamap_unload(sc->buffer_dmat, cm->cm_dmamap); 2097212420Sken } 2098212420Sken 2099230920Sken cm->cm_targ->completed++; 2100230920Sken cm->cm_targ->outstanding--; 2101230920Sken TAILQ_REMOVE(&cm->cm_targ->commands, cm, cm_link); 2102254938Sken ccb->ccb_h.status &= ~(CAM_STATUS_MASK | CAM_SIM_QUEUED); 2103230920Sken 2104230920Sken if (cm->cm_state == MPS_CM_STATE_TIMEDOUT) { 2105230920Sken TAILQ_REMOVE(&cm->cm_targ->timedout_commands, cm, cm_recovery); 2106230920Sken if (cm->cm_reply != NULL) 2107254938Sken mpssas_log_command(cm, MPS_RECOVERY, 2108230920Sken "completed timedout cm %p ccb %p during recovery " 2109230920Sken "ioc %x scsi %x state %x xfer %u\n", 2110230920Sken cm, cm->cm_ccb, 2111237876Sken le16toh(rep->IOCStatus), rep->SCSIStatus, rep->SCSIState, 2112237876Sken le32toh(rep->TransferCount)); 2113230920Sken else 2114254938Sken mpssas_log_command(cm, MPS_RECOVERY, 2115230920Sken "completed timedout cm %p ccb %p during recovery\n", 2116230920Sken cm, cm->cm_ccb); 2117230920Sken } else if (cm->cm_targ->tm != NULL) { 2118230920Sken if (cm->cm_reply != NULL) 2119254938Sken mpssas_log_command(cm, MPS_RECOVERY, 2120230920Sken "completed cm %p ccb %p during recovery " 2121230920Sken "ioc %x scsi %x state %x xfer %u\n", 2122230920Sken cm, cm->cm_ccb, 2123237876Sken le16toh(rep->IOCStatus), rep->SCSIStatus, rep->SCSIState, 2124237876Sken le32toh(rep->TransferCount)); 2125230920Sken else 2126254938Sken mpssas_log_command(cm, MPS_RECOVERY, 2127230920Sken "completed cm %p ccb %p during recovery\n", 2128230920Sken cm, cm->cm_ccb); 2129230920Sken } else if ((sc->mps_flags & MPS_FLAGS_DIAGRESET) != 0) { 2130254938Sken mpssas_log_command(cm, MPS_RECOVERY, 2131230920Sken "reset completed cm %p ccb %p\n", 2132230920Sken cm, cm->cm_ccb); 2133230920Sken } 2134230920Sken 2135218812Sken if ((cm->cm_flags & MPS_CM_FLAGS_ERROR_MASK) != 0) { 2136218812Sken /* 2137218812Sken * We ran into an error after we tried to map the command, 2138218812Sken * so we're getting a callback without queueing the command 2139218812Sken * to the hardware. So we set the status here, and it will 2140218812Sken * be retained below. We'll go through the "fast path", 2141218812Sken * because there can be no reply when we haven't actually 2142218812Sken * gone out to the hardware. 2143218812Sken */ 2144254938Sken ccb->ccb_h.status = CAM_REQUEUE_REQ; 2145218812Sken 2146218812Sken /* 2147218812Sken * Currently the only error included in the mask is 2148218812Sken * MPS_CM_FLAGS_CHAIN_FAILED, which means we're out of 2149218812Sken * chain frames. We need to freeze the queue until we get 2150218812Sken * a command that completed without this error, which will 2151218812Sken * hopefully have some chain frames attached that we can 2152218812Sken * use. If we wanted to get smarter about it, we would 2153218812Sken * only unfreeze the queue in this condition when we're 2154218812Sken * sure that we're getting some chain frames back. That's 2155218812Sken * probably unnecessary. 2156218812Sken */ 2157218812Sken if ((sassc->flags & MPSSAS_QUEUE_FROZEN) == 0) { 2158218812Sken xpt_freeze_simq(sassc->sim, 1); 2159218812Sken sassc->flags |= MPSSAS_QUEUE_FROZEN; 2160254938Sken mps_dprint(sc, MPS_XINFO, "Error sending command, " 2161219036Sken "freezing SIM queue\n"); 2162218812Sken } 2163212420Sken } 2164212420Sken 2165212420Sken /* Take the fast path to completion */ 2166212420Sken if (cm->cm_reply == NULL) { 2167218811Sken if ((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_INPROG) { 2168230920Sken if ((sc->mps_flags & MPS_FLAGS_DIAGRESET) != 0) 2169230920Sken ccb->ccb_h.status = CAM_SCSI_BUS_RESET; 2170230920Sken else { 2171230920Sken ccb->ccb_h.status = CAM_REQ_CMP; 2172230920Sken ccb->csio.scsi_status = SCSI_STATUS_OK; 2173230920Sken } 2174218812Sken if (sassc->flags & MPSSAS_QUEUE_FROZEN) { 2175218812Sken ccb->ccb_h.status |= CAM_RELEASE_SIMQ; 2176218812Sken sassc->flags &= ~MPSSAS_QUEUE_FROZEN; 2177254938Sken mps_dprint(sc, MPS_XINFO, 2178254938Sken "Unfreezing SIM queue\n"); 2179218812Sken } 2180230920Sken } 2181230920Sken 2182230920Sken /* 2183230920Sken * There are two scenarios where the status won't be 2184230920Sken * CAM_REQ_CMP. The first is if MPS_CM_FLAGS_ERROR_MASK is 2185230920Sken * set, the second is in the MPS_FLAGS_DIAGRESET above. 2186230920Sken */ 2187230920Sken if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) { 2188230920Sken /* 2189230920Sken * Freeze the dev queue so that commands are 2190230920Sken * executed in the correct order with after error 2191230920Sken * recovery. 2192230920Sken */ 2193218812Sken ccb->ccb_h.status |= CAM_DEV_QFRZN; 2194218812Sken xpt_freeze_devq(ccb->ccb_h.path, /*count*/ 1); 2195218811Sken } 2196212420Sken mps_free_command(sc, cm); 2197212420Sken xpt_done(ccb); 2198212420Sken return; 2199212420Sken } 2200212420Sken 2201254938Sken mpssas_log_command(cm, MPS_XINFO, 2202254938Sken "ioc %x scsi %x state %x xfer %u\n", 2203254938Sken le16toh(rep->IOCStatus), rep->SCSIStatus, rep->SCSIState, 2204254938Sken le32toh(rep->TransferCount)); 2205212420Sken 2206230920Sken /* 2207230920Sken * If this is a Direct Drive I/O, reissue the I/O to the original IR 2208230920Sken * Volume if an error occurred (normal I/O retry). Use the original 2209230920Sken * CCB, but set a flag that this will be a retry so that it's sent to 2210230920Sken * the original volume. Free the command but reuse the CCB. 2211230920Sken */ 2212230920Sken if (cm->cm_flags & MPS_CM_FLAGS_DD_IO) { 2213230920Sken mps_free_command(sc, cm); 2214230920Sken ccb->ccb_h.status = MPS_WD_RETRY; 2215230920Sken mpssas_action_scsiio(sassc, ccb); 2216230920Sken return; 2217230920Sken } 2218230920Sken 2219237876Sken switch (le16toh(rep->IOCStatus) & MPI2_IOCSTATUS_MASK) { 2220212420Sken case MPI2_IOCSTATUS_SCSI_DATA_UNDERRUN: 2221237876Sken csio->resid = cm->cm_length - le32toh(rep->TransferCount); 2222212420Sken /* FALLTHROUGH */ 2223212420Sken case MPI2_IOCSTATUS_SUCCESS: 2224212420Sken case MPI2_IOCSTATUS_SCSI_RECOVERED_ERROR: 2225230920Sken 2226237876Sken if ((le16toh(rep->IOCStatus) & MPI2_IOCSTATUS_MASK) == 2227230920Sken MPI2_IOCSTATUS_SCSI_RECOVERED_ERROR) 2228254938Sken mpssas_log_command(cm, MPS_XINFO, "recovered error\n"); 2229230920Sken 2230230920Sken /* Completion failed at the transport level. */ 2231230920Sken if (rep->SCSIState & (MPI2_SCSI_STATE_NO_SCSI_STATUS | 2232230920Sken MPI2_SCSI_STATE_TERMINATED)) { 2233230920Sken ccb->ccb_h.status = CAM_REQ_CMP_ERR; 2234230920Sken break; 2235230920Sken } 2236230920Sken 2237230920Sken /* In a modern packetized environment, an autosense failure 2238230920Sken * implies that there's not much else that can be done to 2239230920Sken * recover the command. 2240230920Sken */ 2241230920Sken if (rep->SCSIState & MPI2_SCSI_STATE_AUTOSENSE_FAILED) { 2242230920Sken ccb->ccb_h.status = CAM_AUTOSENSE_FAIL; 2243230920Sken break; 2244230920Sken } 2245230920Sken 2246230920Sken /* 2247230920Sken * CAM doesn't care about SAS Response Info data, but if this is 2248230920Sken * the state check if TLR should be done. If not, clear the 2249230920Sken * TLR_bits for the target. 2250230920Sken */ 2251230920Sken if ((rep->SCSIState & MPI2_SCSI_STATE_RESPONSE_INFO_VALID) && 2252237876Sken ((le32toh(rep->ResponseInfo) & MPI2_SCSI_RI_MASK_REASONCODE) == 2253230920Sken MPS_SCSI_RI_INVALID_FRAME)) { 2254230920Sken sc->mapping_table[csio->ccb_h.target_id].TLR_bits = 2255230920Sken (u8)MPI2_SCSIIO_CONTROL_NO_TLR; 2256230920Sken } 2257230920Sken 2258230920Sken /* 2259230920Sken * Intentionally override the normal SCSI status reporting 2260230920Sken * for these two cases. These are likely to happen in a 2261230920Sken * multi-initiator environment, and we want to make sure that 2262230920Sken * CAM retries these commands rather than fail them. 2263230920Sken */ 2264230920Sken if ((rep->SCSIStatus == MPI2_SCSI_STATUS_COMMAND_TERMINATED) || 2265230920Sken (rep->SCSIStatus == MPI2_SCSI_STATUS_TASK_ABORTED)) { 2266230920Sken ccb->ccb_h.status = CAM_REQ_ABORTED; 2267230920Sken break; 2268230920Sken } 2269230920Sken 2270230920Sken /* Handle normal status and sense */ 2271230920Sken csio->scsi_status = rep->SCSIStatus; 2272230920Sken if (rep->SCSIStatus == MPI2_SCSI_STATUS_GOOD) 2273230920Sken ccb->ccb_h.status = CAM_REQ_CMP; 2274230920Sken else 2275230920Sken ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR; 2276230920Sken 2277230920Sken if (rep->SCSIState & MPI2_SCSI_STATE_AUTOSENSE_VALID) { 2278230920Sken int sense_len, returned_sense_len; 2279230920Sken 2280237876Sken returned_sense_len = min(le32toh(rep->SenseCount), 2281230920Sken sizeof(struct scsi_sense_data)); 2282230920Sken if (returned_sense_len < ccb->csio.sense_len) 2283230920Sken ccb->csio.sense_resid = ccb->csio.sense_len - 2284230920Sken returned_sense_len; 2285230920Sken else 2286230920Sken ccb->csio.sense_resid = 0; 2287230920Sken 2288230920Sken sense_len = min(returned_sense_len, 2289230920Sken ccb->csio.sense_len - ccb->csio.sense_resid); 2290230920Sken bzero(&ccb->csio.sense_data, 2291238013Smarius sizeof(ccb->csio.sense_data)); 2292230920Sken bcopy(cm->cm_sense, &ccb->csio.sense_data, sense_len); 2293230920Sken ccb->ccb_h.status |= CAM_AUTOSNS_VALID; 2294230920Sken } 2295230920Sken 2296230920Sken /* 2297230920Sken * Check if this is an INQUIRY command. If it's a VPD inquiry, 2298230920Sken * and it's page code 0 (Supported Page List), and there is 2299230920Sken * inquiry data, and this is for a sequential access device, and 2300230920Sken * the device is an SSP target, and TLR is supported by the 2301230920Sken * controller, turn the TLR_bits value ON if page 0x90 is 2302230920Sken * supported. 2303230920Sken */ 2304230920Sken if ((csio->cdb_io.cdb_bytes[0] == INQUIRY) && 2305230920Sken (csio->cdb_io.cdb_bytes[1] & SI_EVPD) && 2306230920Sken (csio->cdb_io.cdb_bytes[2] == SVPD_SUPPORTED_PAGE_LIST) && 2307251899Sscottl ((csio->ccb_h.flags & CAM_DATA_MASK) == CAM_DATA_VADDR) && 2308266549Sken (csio->data_ptr != NULL) && 2309266549Sken ((csio->data_ptr[0] & 0x1f) == T_SEQUENTIAL) && 2310266549Sken (sc->control_TLR) && 2311230920Sken (sc->mapping_table[csio->ccb_h.target_id].device_info & 2312230920Sken MPI2_SAS_DEVICE_INFO_SSP_TARGET)) { 2313230920Sken vpd_list = (struct scsi_vpd_supported_page_list *) 2314230920Sken csio->data_ptr; 2315230920Sken TLR_bits = &sc->mapping_table[csio->ccb_h.target_id]. 2316230920Sken TLR_bits; 2317230920Sken *TLR_bits = (u8)MPI2_SCSIIO_CONTROL_NO_TLR; 2318230920Sken TLR_on = (u8)MPI2_SCSIIO_CONTROL_TLR_ON; 2319230920Sken alloc_len = ((u16)csio->cdb_io.cdb_bytes[3] << 8) + 2320230920Sken csio->cdb_io.cdb_bytes[4]; 2321266549Sken alloc_len -= csio->resid; 2322230920Sken for (i = 0; i < MIN(vpd_list->length, alloc_len); i++) { 2323230920Sken if (vpd_list->list[i] == 0x90) { 2324230920Sken *TLR_bits = TLR_on; 2325230920Sken break; 2326230920Sken } 2327230920Sken } 2328230920Sken } 2329212420Sken break; 2330212420Sken case MPI2_IOCSTATUS_SCSI_INVALID_DEVHANDLE: 2331212420Sken case MPI2_IOCSTATUS_SCSI_DEVICE_NOT_THERE: 2332230920Sken /* 2333230920Sken * If devinfo is 0 this will be a volume. In that case don't 2334230920Sken * tell CAM that the volume is not there. We want volumes to 2335230920Sken * be enumerated until they are deleted/removed, not just 2336230920Sken * failed. 2337230920Sken */ 2338230920Sken if (cm->cm_targ->devinfo == 0) 2339230920Sken ccb->ccb_h.status = CAM_REQ_CMP; 2340230920Sken else 2341230920Sken ccb->ccb_h.status = CAM_DEV_NOT_THERE; 2342212420Sken break; 2343230920Sken case MPI2_IOCSTATUS_INVALID_SGL: 2344230920Sken mps_print_scsiio_cmd(sc, cm); 2345230920Sken ccb->ccb_h.status = CAM_UNREC_HBA_ERROR; 2346230920Sken break; 2347212420Sken case MPI2_IOCSTATUS_SCSI_TASK_TERMINATED: 2348212420Sken /* 2349212420Sken * This is one of the responses that comes back when an I/O 2350212420Sken * has been aborted. If it is because of a timeout that we 2351212420Sken * initiated, just set the status to CAM_CMD_TIMEOUT. 2352212420Sken * Otherwise set it to CAM_REQ_ABORTED. The effect on the 2353212420Sken * command is the same (it gets retried, subject to the 2354212420Sken * retry counter), the only difference is what gets printed 2355212420Sken * on the console. 2356212420Sken */ 2357212420Sken if (cm->cm_state == MPS_CM_STATE_TIMEDOUT) 2358212420Sken ccb->ccb_h.status = CAM_CMD_TIMEOUT; 2359212420Sken else 2360212420Sken ccb->ccb_h.status = CAM_REQ_ABORTED; 2361212420Sken break; 2362230920Sken case MPI2_IOCSTATUS_SCSI_DATA_OVERRUN: 2363230920Sken /* resid is ignored for this condition */ 2364230920Sken csio->resid = 0; 2365230920Sken ccb->ccb_h.status = CAM_DATA_RUN_ERR; 2366230920Sken break; 2367212420Sken case MPI2_IOCSTATUS_SCSI_IOC_TERMINATED: 2368212420Sken case MPI2_IOCSTATUS_SCSI_EXT_TERMINATED: 2369230920Sken /* 2370230920Sken * Since these are generally external (i.e. hopefully 2371230920Sken * transient transport-related) errors, retry these without 2372230920Sken * decrementing the retry count. 2373230920Sken */ 2374218812Sken ccb->ccb_h.status = CAM_REQUEUE_REQ; 2375254938Sken mpssas_log_command(cm, MPS_INFO, 2376230920Sken "terminated ioc %x scsi %x state %x xfer %u\n", 2377254938Sken le16toh(rep->IOCStatus), rep->SCSIStatus, rep->SCSIState, 2378254938Sken le32toh(rep->TransferCount)); 2379212420Sken break; 2380212420Sken case MPI2_IOCSTATUS_INVALID_FUNCTION: 2381212420Sken case MPI2_IOCSTATUS_INTERNAL_ERROR: 2382212420Sken case MPI2_IOCSTATUS_INVALID_VPID: 2383212420Sken case MPI2_IOCSTATUS_INVALID_FIELD: 2384212420Sken case MPI2_IOCSTATUS_INVALID_STATE: 2385212420Sken case MPI2_IOCSTATUS_OP_STATE_NOT_SUPPORTED: 2386212420Sken case MPI2_IOCSTATUS_SCSI_IO_DATA_ERROR: 2387212420Sken case MPI2_IOCSTATUS_SCSI_PROTOCOL_ERROR: 2388212420Sken case MPI2_IOCSTATUS_SCSI_RESIDUAL_MISMATCH: 2389212420Sken case MPI2_IOCSTATUS_SCSI_TASK_MGMT_FAILED: 2390212420Sken default: 2391254938Sken mpssas_log_command(cm, MPS_XINFO, 2392230920Sken "completed ioc %x scsi %x state %x xfer %u\n", 2393254938Sken le16toh(rep->IOCStatus), rep->SCSIStatus, rep->SCSIState, 2394254938Sken le32toh(rep->TransferCount)); 2395230920Sken csio->resid = cm->cm_length; 2396212420Sken ccb->ccb_h.status = CAM_REQ_CMP_ERR; 2397230920Sken break; 2398212420Sken } 2399231679Sken 2400231679Sken mps_sc_failed_io_info(sc,csio,rep); 2401212420Sken 2402230920Sken if (sassc->flags & MPSSAS_QUEUE_FROZEN) { 2403230920Sken ccb->ccb_h.status |= CAM_RELEASE_SIMQ; 2404230920Sken sassc->flags &= ~MPSSAS_QUEUE_FROZEN; 2405254938Sken mps_dprint(sc, MPS_XINFO, "Command completed, " 2406254938Sken "unfreezing SIM queue\n"); 2407230920Sken } 2408212420Sken 2409230920Sken if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) { 2410230920Sken ccb->ccb_h.status |= CAM_DEV_QFRZN; 2411230920Sken xpt_freeze_devq(ccb->ccb_h.path, /*count*/ 1); 2412230920Sken } 2413212420Sken 2414230920Sken mps_free_command(sc, cm); 2415230920Sken xpt_done(ccb); 2416230920Sken} 2417230920Sken 2418237876Sken/* All Request reached here are Endian safe */ 2419230920Skenstatic void 2420230920Skenmpssas_direct_drive_io(struct mpssas_softc *sassc, struct mps_command *cm, 2421230920Sken union ccb *ccb) { 2422230920Sken pMpi2SCSIIORequest_t pIO_req; 2423230920Sken struct mps_softc *sc = sassc->sc; 2424230920Sken uint64_t virtLBA; 2425230920Sken uint32_t physLBA, stripe_offset, stripe_unit; 2426230920Sken uint32_t io_size, column; 2427230920Sken uint8_t *ptrLBA, lba_idx, physLBA_byte, *CDB; 2428230920Sken 2429230920Sken /* 2430230920Sken * If this is a valid SCSI command (Read6, Read10, Read16, Write6, 2431230920Sken * Write10, or Write16), build a direct I/O message. Otherwise, the I/O 2432230920Sken * will be sent to the IR volume itself. Since Read6 and Write6 are a 2433230920Sken * bit different than the 10/16 CDBs, handle them separately. 2434230920Sken */ 2435230920Sken pIO_req = (pMpi2SCSIIORequest_t)cm->cm_req; 2436230920Sken CDB = pIO_req->CDB.CDB32; 2437230920Sken 2438230920Sken /* 2439230920Sken * Handle 6 byte CDBs. 2440230920Sken */ 2441230920Sken if ((pIO_req->DevHandle == sc->DD_dev_handle) && ((CDB[0] == READ_6) || 2442230920Sken (CDB[0] == WRITE_6))) { 2443230920Sken /* 2444230920Sken * Get the transfer size in blocks. 2445230920Sken */ 2446230920Sken io_size = (cm->cm_length >> sc->DD_block_exponent); 2447230920Sken 2448230920Sken /* 2449230920Sken * Get virtual LBA given in the CDB. 2450230920Sken */ 2451230920Sken virtLBA = ((uint64_t)(CDB[1] & 0x1F) << 16) | 2452230920Sken ((uint64_t)CDB[2] << 8) | (uint64_t)CDB[3]; 2453230920Sken 2454230920Sken /* 2455230920Sken * Check that LBA range for I/O does not exceed volume's 2456230920Sken * MaxLBA. 2457230920Sken */ 2458230920Sken if ((virtLBA + (uint64_t)io_size - 1) <= 2459230920Sken sc->DD_max_lba) { 2460230920Sken /* 2461230920Sken * Check if the I/O crosses a stripe boundary. If not, 2462230920Sken * translate the virtual LBA to a physical LBA and set 2463230920Sken * the DevHandle for the PhysDisk to be used. If it 2464230920Sken * does cross a boundry, do normal I/O. To get the 2465230920Sken * right DevHandle to use, get the map number for the 2466230920Sken * column, then use that map number to look up the 2467230920Sken * DevHandle of the PhysDisk. 2468230920Sken */ 2469230920Sken stripe_offset = (uint32_t)virtLBA & 2470230920Sken (sc->DD_stripe_size - 1); 2471230920Sken if ((stripe_offset + io_size) <= sc->DD_stripe_size) { 2472230920Sken physLBA = (uint32_t)virtLBA >> 2473230920Sken sc->DD_stripe_exponent; 2474230920Sken stripe_unit = physLBA / sc->DD_num_phys_disks; 2475230920Sken column = physLBA % sc->DD_num_phys_disks; 2476230920Sken pIO_req->DevHandle = 2477237876Sken htole16(sc->DD_column_map[column].dev_handle); 2478237876Sken /* ???? Is this endian safe*/ 2479230920Sken cm->cm_desc.SCSIIO.DevHandle = 2480230920Sken pIO_req->DevHandle; 2481230920Sken 2482230920Sken physLBA = (stripe_unit << 2483230920Sken sc->DD_stripe_exponent) + stripe_offset; 2484230920Sken ptrLBA = &pIO_req->CDB.CDB32[1]; 2485230920Sken physLBA_byte = (uint8_t)(physLBA >> 16); 2486230920Sken *ptrLBA = physLBA_byte; 2487230920Sken ptrLBA = &pIO_req->CDB.CDB32[2]; 2488230920Sken physLBA_byte = (uint8_t)(physLBA >> 8); 2489230920Sken *ptrLBA = physLBA_byte; 2490230920Sken ptrLBA = &pIO_req->CDB.CDB32[3]; 2491230920Sken physLBA_byte = (uint8_t)physLBA; 2492230920Sken *ptrLBA = physLBA_byte; 2493230920Sken 2494230920Sken /* 2495230920Sken * Set flag that Direct Drive I/O is 2496230920Sken * being done. 2497230920Sken */ 2498230920Sken cm->cm_flags |= MPS_CM_FLAGS_DD_IO; 2499230920Sken } 2500212420Sken } 2501230920Sken return; 2502212420Sken } 2503212420Sken 2504230920Sken /* 2505237876Sken * Handle 10, 12 or 16 byte CDBs. 2506230920Sken */ 2507230920Sken if ((pIO_req->DevHandle == sc->DD_dev_handle) && ((CDB[0] == READ_10) || 2508230920Sken (CDB[0] == WRITE_10) || (CDB[0] == READ_16) || 2509237876Sken (CDB[0] == WRITE_16) || (CDB[0] == READ_12) || 2510237876Sken (CDB[0] == WRITE_12))) { 2511230920Sken /* 2512230920Sken * For 16-byte CDB's, verify that the upper 4 bytes of the CDB 2513230920Sken * are 0. If not, this is accessing beyond 2TB so handle it in 2514237876Sken * the else section. 10-byte and 12-byte CDB's are OK. 2515237876Sken * FreeBSD sends very rare 12 byte READ/WRITE, but driver is 2516237876Sken * ready to accept 12byte CDB for Direct IOs. 2517230920Sken */ 2518237876Sken if ((CDB[0] == READ_10 || CDB[0] == WRITE_10) || 2519237876Sken (CDB[0] == READ_12 || CDB[0] == WRITE_12) || 2520230920Sken !(CDB[2] | CDB[3] | CDB[4] | CDB[5])) { 2521230920Sken /* 2522230920Sken * Get the transfer size in blocks. 2523230920Sken */ 2524230920Sken io_size = (cm->cm_length >> sc->DD_block_exponent); 2525226067Sken 2526230920Sken /* 2527230920Sken * Get virtual LBA. Point to correct lower 4 bytes of 2528230920Sken * LBA in the CDB depending on command. 2529230920Sken */ 2530237876Sken lba_idx = ((CDB[0] == READ_12) || 2531237876Sken (CDB[0] == WRITE_12) || 2532237876Sken (CDB[0] == READ_10) || 2533237876Sken (CDB[0] == WRITE_10))? 2 : 6; 2534230920Sken virtLBA = ((uint64_t)CDB[lba_idx] << 24) | 2535230920Sken ((uint64_t)CDB[lba_idx + 1] << 16) | 2536230920Sken ((uint64_t)CDB[lba_idx + 2] << 8) | 2537230920Sken (uint64_t)CDB[lba_idx + 3]; 2538226067Sken 2539230920Sken /* 2540230920Sken * Check that LBA range for I/O does not exceed volume's 2541230920Sken * MaxLBA. 2542230920Sken */ 2543230920Sken if ((virtLBA + (uint64_t)io_size - 1) <= 2544230920Sken sc->DD_max_lba) { 2545230920Sken /* 2546230920Sken * Check if the I/O crosses a stripe boundary. 2547230920Sken * If not, translate the virtual LBA to a 2548230920Sken * physical LBA and set the DevHandle for the 2549230920Sken * PhysDisk to be used. If it does cross a 2550230920Sken * boundry, do normal I/O. To get the right 2551230920Sken * DevHandle to use, get the map number for the 2552230920Sken * column, then use that map number to look up 2553230920Sken * the DevHandle of the PhysDisk. 2554230920Sken */ 2555230920Sken stripe_offset = (uint32_t)virtLBA & 2556230920Sken (sc->DD_stripe_size - 1); 2557230920Sken if ((stripe_offset + io_size) <= 2558230920Sken sc->DD_stripe_size) { 2559230920Sken physLBA = (uint32_t)virtLBA >> 2560230920Sken sc->DD_stripe_exponent; 2561230920Sken stripe_unit = physLBA / 2562230920Sken sc->DD_num_phys_disks; 2563230920Sken column = physLBA % 2564230920Sken sc->DD_num_phys_disks; 2565230920Sken pIO_req->DevHandle = 2566237876Sken htole16(sc->DD_column_map[column]. 2567237876Sken dev_handle); 2568230920Sken cm->cm_desc.SCSIIO.DevHandle = 2569230920Sken pIO_req->DevHandle; 2570212420Sken 2571230920Sken physLBA = (stripe_unit << 2572230920Sken sc->DD_stripe_exponent) + 2573230920Sken stripe_offset; 2574230920Sken ptrLBA = 2575230920Sken &pIO_req->CDB.CDB32[lba_idx]; 2576230920Sken physLBA_byte = (uint8_t)(physLBA >> 24); 2577230920Sken *ptrLBA = physLBA_byte; 2578230920Sken ptrLBA = 2579230920Sken &pIO_req->CDB.CDB32[lba_idx + 1]; 2580230920Sken physLBA_byte = (uint8_t)(physLBA >> 16); 2581230920Sken *ptrLBA = physLBA_byte; 2582230920Sken ptrLBA = 2583230920Sken &pIO_req->CDB.CDB32[lba_idx + 2]; 2584230920Sken physLBA_byte = (uint8_t)(physLBA >> 8); 2585230920Sken *ptrLBA = physLBA_byte; 2586230920Sken ptrLBA = 2587230920Sken &pIO_req->CDB.CDB32[lba_idx + 3]; 2588230920Sken physLBA_byte = (uint8_t)physLBA; 2589230920Sken *ptrLBA = physLBA_byte; 2590212420Sken 2591230920Sken /* 2592230920Sken * Set flag that Direct Drive I/O is 2593230920Sken * being done. 2594230920Sken */ 2595230920Sken cm->cm_flags |= MPS_CM_FLAGS_DD_IO; 2596230920Sken } 2597230920Sken } 2598230920Sken } else { 2599230920Sken /* 2600230920Sken * 16-byte CDB and the upper 4 bytes of the CDB are not 2601230920Sken * 0. Get the transfer size in blocks. 2602230920Sken */ 2603230920Sken io_size = (cm->cm_length >> sc->DD_block_exponent); 2604212420Sken 2605230920Sken /* 2606230920Sken * Get virtual LBA. 2607230920Sken */ 2608230920Sken virtLBA = ((uint64_t)CDB[2] << 54) | 2609230920Sken ((uint64_t)CDB[3] << 48) | 2610230920Sken ((uint64_t)CDB[4] << 40) | 2611230920Sken ((uint64_t)CDB[5] << 32) | 2612230920Sken ((uint64_t)CDB[6] << 24) | 2613230920Sken ((uint64_t)CDB[7] << 16) | 2614230920Sken ((uint64_t)CDB[8] << 8) | 2615230920Sken (uint64_t)CDB[9]; 2616230920Sken 2617230920Sken /* 2618230920Sken * Check that LBA range for I/O does not exceed volume's 2619230920Sken * MaxLBA. 2620230920Sken */ 2621230920Sken if ((virtLBA + (uint64_t)io_size - 1) <= 2622230920Sken sc->DD_max_lba) { 2623230920Sken /* 2624230920Sken * Check if the I/O crosses a stripe boundary. 2625230920Sken * If not, translate the virtual LBA to a 2626230920Sken * physical LBA and set the DevHandle for the 2627230920Sken * PhysDisk to be used. If it does cross a 2628230920Sken * boundry, do normal I/O. To get the right 2629230920Sken * DevHandle to use, get the map number for the 2630230920Sken * column, then use that map number to look up 2631230920Sken * the DevHandle of the PhysDisk. 2632230920Sken */ 2633230920Sken stripe_offset = (uint32_t)virtLBA & 2634230920Sken (sc->DD_stripe_size - 1); 2635230920Sken if ((stripe_offset + io_size) <= 2636230920Sken sc->DD_stripe_size) { 2637230920Sken physLBA = (uint32_t)(virtLBA >> 2638230920Sken sc->DD_stripe_exponent); 2639230920Sken stripe_unit = physLBA / 2640230920Sken sc->DD_num_phys_disks; 2641230920Sken column = physLBA % 2642230920Sken sc->DD_num_phys_disks; 2643230920Sken pIO_req->DevHandle = 2644237876Sken htole16(sc->DD_column_map[column]. 2645237876Sken dev_handle); 2646230920Sken cm->cm_desc.SCSIIO.DevHandle = 2647230920Sken pIO_req->DevHandle; 2648230920Sken 2649230920Sken physLBA = (stripe_unit << 2650230920Sken sc->DD_stripe_exponent) + 2651230920Sken stripe_offset; 2652230920Sken 2653230920Sken /* 2654230920Sken * Set upper 4 bytes of LBA to 0. We 2655230920Sken * assume that the phys disks are less 2656230920Sken * than 2 TB's in size. Then, set the 2657230920Sken * lower 4 bytes. 2658230920Sken */ 2659230920Sken pIO_req->CDB.CDB32[2] = 0; 2660230920Sken pIO_req->CDB.CDB32[3] = 0; 2661230920Sken pIO_req->CDB.CDB32[4] = 0; 2662230920Sken pIO_req->CDB.CDB32[5] = 0; 2663230920Sken ptrLBA = &pIO_req->CDB.CDB32[6]; 2664230920Sken physLBA_byte = (uint8_t)(physLBA >> 24); 2665230920Sken *ptrLBA = physLBA_byte; 2666230920Sken ptrLBA = &pIO_req->CDB.CDB32[7]; 2667230920Sken physLBA_byte = (uint8_t)(physLBA >> 16); 2668230920Sken *ptrLBA = physLBA_byte; 2669230920Sken ptrLBA = &pIO_req->CDB.CDB32[8]; 2670230920Sken physLBA_byte = (uint8_t)(physLBA >> 8); 2671230920Sken *ptrLBA = physLBA_byte; 2672230920Sken ptrLBA = &pIO_req->CDB.CDB32[9]; 2673230920Sken physLBA_byte = (uint8_t)physLBA; 2674230920Sken *ptrLBA = physLBA_byte; 2675230920Sken 2676230920Sken /* 2677230920Sken * Set flag that Direct Drive I/O is 2678230920Sken * being done. 2679230920Sken */ 2680230920Sken cm->cm_flags |= MPS_CM_FLAGS_DD_IO; 2681230920Sken } 2682230920Sken } 2683230920Sken } 2684218812Sken } 2685212420Sken} 2686212420Sken 2687216088Sken#if __FreeBSD_version >= 900026 2688212420Skenstatic void 2689216088Skenmpssas_smpio_complete(struct mps_softc *sc, struct mps_command *cm) 2690216088Sken{ 2691216088Sken MPI2_SMP_PASSTHROUGH_REPLY *rpl; 2692216088Sken MPI2_SMP_PASSTHROUGH_REQUEST *req; 2693216088Sken uint64_t sasaddr; 2694216088Sken union ccb *ccb; 2695216088Sken 2696216088Sken ccb = cm->cm_complete_data; 2697218812Sken 2698218812Sken /* 2699218812Sken * Currently there should be no way we can hit this case. It only 2700218812Sken * happens when we have a failure to allocate chain frames, and SMP 2701218812Sken * commands require two S/G elements only. That should be handled 2702218812Sken * in the standard request size. 2703218812Sken */ 2704218812Sken if ((cm->cm_flags & MPS_CM_FLAGS_ERROR_MASK) != 0) { 2705254938Sken mps_dprint(sc, MPS_ERROR,"%s: cm_flags = %#x on SMP request!\n", 2706218812Sken __func__, cm->cm_flags); 2707218812Sken ccb->ccb_h.status = CAM_REQ_CMP_ERR; 2708218812Sken goto bailout; 2709230920Sken } 2710218812Sken 2711216088Sken rpl = (MPI2_SMP_PASSTHROUGH_REPLY *)cm->cm_reply; 2712216088Sken if (rpl == NULL) { 2713254938Sken mps_dprint(sc, MPS_ERROR, "%s: NULL cm_reply!\n", __func__); 2714216088Sken ccb->ccb_h.status = CAM_REQ_CMP_ERR; 2715216088Sken goto bailout; 2716216088Sken } 2717216088Sken 2718216088Sken req = (MPI2_SMP_PASSTHROUGH_REQUEST *)cm->cm_req; 2719216088Sken sasaddr = le32toh(req->SASAddress.Low); 2720216088Sken sasaddr |= ((uint64_t)(le32toh(req->SASAddress.High))) << 32; 2721216088Sken 2722254938Sken if ((le16toh(rpl->IOCStatus) & MPI2_IOCSTATUS_MASK) != 2723254938Sken MPI2_IOCSTATUS_SUCCESS || 2724216088Sken rpl->SASStatus != MPI2_SASSTATUS_SUCCESS) { 2725254938Sken mps_dprint(sc, MPS_XINFO, "%s: IOCStatus %04x SASStatus %02x\n", 2726237876Sken __func__, le16toh(rpl->IOCStatus), rpl->SASStatus); 2727216088Sken ccb->ccb_h.status = CAM_REQ_CMP_ERR; 2728216088Sken goto bailout; 2729216088Sken } 2730216088Sken 2731254938Sken mps_dprint(sc, MPS_XINFO, "%s: SMP request to SAS address " 2732216088Sken "%#jx completed successfully\n", __func__, 2733216088Sken (uintmax_t)sasaddr); 2734216088Sken 2735216088Sken if (ccb->smpio.smp_response[2] == SMP_FR_ACCEPTED) 2736216088Sken ccb->ccb_h.status = CAM_REQ_CMP; 2737216088Sken else 2738216088Sken ccb->ccb_h.status = CAM_SMP_STATUS_ERROR; 2739216088Sken 2740216088Skenbailout: 2741216088Sken /* 2742216088Sken * We sync in both directions because we had DMAs in the S/G list 2743216088Sken * in both directions. 2744216088Sken */ 2745216088Sken bus_dmamap_sync(sc->buffer_dmat, cm->cm_dmamap, 2746216088Sken BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); 2747216088Sken bus_dmamap_unload(sc->buffer_dmat, cm->cm_dmamap); 2748216088Sken mps_free_command(sc, cm); 2749216088Sken xpt_done(ccb); 2750216088Sken} 2751216088Sken 2752216088Skenstatic void 2753216088Skenmpssas_send_smpcmd(struct mpssas_softc *sassc, union ccb *ccb, uint64_t sasaddr) 2754216088Sken{ 2755216088Sken struct mps_command *cm; 2756216088Sken uint8_t *request, *response; 2757216088Sken MPI2_SMP_PASSTHROUGH_REQUEST *req; 2758216088Sken struct mps_softc *sc; 2759216088Sken struct sglist *sg; 2760216088Sken int error; 2761216088Sken 2762216088Sken sc = sassc->sc; 2763216088Sken sg = NULL; 2764216088Sken error = 0; 2765216088Sken 2766216088Sken /* 2767216088Sken * XXX We don't yet support physical addresses here. 2768216088Sken */ 2769251874Sscottl switch ((ccb->ccb_h.flags & CAM_DATA_MASK)) { 2770251874Sscottl case CAM_DATA_PADDR: 2771251874Sscottl case CAM_DATA_SG_PADDR: 2772254938Sken mps_dprint(sc, MPS_ERROR, 2773254938Sken "%s: physical addresses not supported\n", __func__); 2774216088Sken ccb->ccb_h.status = CAM_REQ_INVALID; 2775216088Sken xpt_done(ccb); 2776216088Sken return; 2777251874Sscottl case CAM_DATA_SG: 2778216088Sken /* 2779216088Sken * The chip does not support more than one buffer for the 2780216088Sken * request or response. 2781216088Sken */ 2782216088Sken if ((ccb->smpio.smp_request_sglist_cnt > 1) 2783216088Sken || (ccb->smpio.smp_response_sglist_cnt > 1)) { 2784254938Sken mps_dprint(sc, MPS_ERROR, 2785254938Sken "%s: multiple request or response " 2786216088Sken "buffer segments not supported for SMP\n", 2787216088Sken __func__); 2788216088Sken ccb->ccb_h.status = CAM_REQ_INVALID; 2789216088Sken xpt_done(ccb); 2790216088Sken return; 2791216088Sken } 2792216088Sken 2793216088Sken /* 2794216088Sken * The CAM_SCATTER_VALID flag was originally implemented 2795216088Sken * for the XPT_SCSI_IO CCB, which only has one data pointer. 2796216088Sken * We have two. So, just take that flag to mean that we 2797216088Sken * might have S/G lists, and look at the S/G segment count 2798216088Sken * to figure out whether that is the case for each individual 2799216088Sken * buffer. 2800216088Sken */ 2801216088Sken if (ccb->smpio.smp_request_sglist_cnt != 0) { 2802216088Sken bus_dma_segment_t *req_sg; 2803216088Sken 2804216088Sken req_sg = (bus_dma_segment_t *)ccb->smpio.smp_request; 2805256233Smav request = (uint8_t *)(uintptr_t)req_sg[0].ds_addr; 2806216088Sken } else 2807216088Sken request = ccb->smpio.smp_request; 2808216088Sken 2809216088Sken if (ccb->smpio.smp_response_sglist_cnt != 0) { 2810216088Sken bus_dma_segment_t *rsp_sg; 2811216088Sken 2812216088Sken rsp_sg = (bus_dma_segment_t *)ccb->smpio.smp_response; 2813256233Smav response = (uint8_t *)(uintptr_t)rsp_sg[0].ds_addr; 2814216088Sken } else 2815216088Sken response = ccb->smpio.smp_response; 2816251874Sscottl break; 2817251874Sscottl case CAM_DATA_VADDR: 2818216088Sken request = ccb->smpio.smp_request; 2819216088Sken response = ccb->smpio.smp_response; 2820251874Sscottl break; 2821251874Sscottl default: 2822251874Sscottl ccb->ccb_h.status = CAM_REQ_INVALID; 2823251874Sscottl xpt_done(ccb); 2824251874Sscottl return; 2825216088Sken } 2826216088Sken 2827216088Sken cm = mps_alloc_command(sc); 2828216088Sken if (cm == NULL) { 2829254938Sken mps_dprint(sc, MPS_ERROR, 2830254938Sken "%s: cannot allocate command\n", __func__); 2831216088Sken ccb->ccb_h.status = CAM_RESRC_UNAVAIL; 2832216088Sken xpt_done(ccb); 2833216088Sken return; 2834216088Sken } 2835216088Sken 2836216088Sken req = (MPI2_SMP_PASSTHROUGH_REQUEST *)cm->cm_req; 2837216088Sken bzero(req, sizeof(*req)); 2838216088Sken req->Function = MPI2_FUNCTION_SMP_PASSTHROUGH; 2839216088Sken 2840216088Sken /* Allow the chip to use any route to this SAS address. */ 2841216088Sken req->PhysicalPort = 0xff; 2842216088Sken 2843237876Sken req->RequestDataLength = htole16(ccb->smpio.smp_request_len); 2844216088Sken req->SGLFlags = 2845216088Sken MPI2_SGLFLAGS_SYSTEM_ADDRESS_SPACE | MPI2_SGLFLAGS_SGL_TYPE_MPI; 2846216088Sken 2847254938Sken mps_dprint(sc, MPS_XINFO, "%s: sending SMP request to SAS " 2848254938Sken "address %#jx\n", __func__, (uintmax_t)sasaddr); 2849216088Sken 2850216088Sken mpi_init_sge(cm, req, &req->SGL); 2851216088Sken 2852216088Sken /* 2853216088Sken * Set up a uio to pass into mps_map_command(). This allows us to 2854216088Sken * do one map command, and one busdma call in there. 2855216088Sken */ 2856216088Sken cm->cm_uio.uio_iov = cm->cm_iovec; 2857216088Sken cm->cm_uio.uio_iovcnt = 2; 2858216088Sken cm->cm_uio.uio_segflg = UIO_SYSSPACE; 2859216088Sken 2860216088Sken /* 2861216088Sken * The read/write flag isn't used by busdma, but set it just in 2862216088Sken * case. This isn't exactly accurate, either, since we're going in 2863216088Sken * both directions. 2864216088Sken */ 2865216088Sken cm->cm_uio.uio_rw = UIO_WRITE; 2866216088Sken 2867216088Sken cm->cm_iovec[0].iov_base = request; 2868237876Sken cm->cm_iovec[0].iov_len = le16toh(req->RequestDataLength); 2869216088Sken cm->cm_iovec[1].iov_base = response; 2870216088Sken cm->cm_iovec[1].iov_len = ccb->smpio.smp_response_len; 2871216088Sken 2872216088Sken cm->cm_uio.uio_resid = cm->cm_iovec[0].iov_len + 2873216088Sken cm->cm_iovec[1].iov_len; 2874216088Sken 2875216088Sken /* 2876216088Sken * Trigger a warning message in mps_data_cb() for the user if we 2877216088Sken * wind up exceeding two S/G segments. The chip expects one 2878216088Sken * segment for the request and another for the response. 2879216088Sken */ 2880216088Sken cm->cm_max_segs = 2; 2881216088Sken 2882216088Sken cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 2883216088Sken cm->cm_complete = mpssas_smpio_complete; 2884216088Sken cm->cm_complete_data = ccb; 2885216088Sken 2886216088Sken /* 2887216088Sken * Tell the mapping code that we're using a uio, and that this is 2888216088Sken * an SMP passthrough request. There is a little special-case 2889216088Sken * logic there (in mps_data_cb()) to handle the bidirectional 2890216088Sken * transfer. 2891216088Sken */ 2892216088Sken cm->cm_flags |= MPS_CM_FLAGS_USE_UIO | MPS_CM_FLAGS_SMP_PASS | 2893216088Sken MPS_CM_FLAGS_DATAIN | MPS_CM_FLAGS_DATAOUT; 2894216088Sken 2895216088Sken /* The chip data format is little endian. */ 2896216088Sken req->SASAddress.High = htole32(sasaddr >> 32); 2897216088Sken req->SASAddress.Low = htole32(sasaddr); 2898216088Sken 2899216088Sken /* 2900216088Sken * XXX Note that we don't have a timeout/abort mechanism here. 2901216088Sken * From the manual, it looks like task management requests only 2902216088Sken * work for SCSI IO and SATA passthrough requests. We may need to 2903216088Sken * have a mechanism to retry requests in the event of a chip reset 2904216088Sken * at least. Hopefully the chip will insure that any errors short 2905216088Sken * of that are relayed back to the driver. 2906216088Sken */ 2907216088Sken error = mps_map_command(sc, cm); 2908216088Sken if ((error != 0) && (error != EINPROGRESS)) { 2909254938Sken mps_dprint(sc, MPS_ERROR, 2910254938Sken "%s: error %d returned from mps_map_command()\n", 2911216088Sken __func__, error); 2912216088Sken goto bailout_error; 2913216088Sken } 2914216088Sken 2915216088Sken return; 2916216088Sken 2917216088Skenbailout_error: 2918216088Sken mps_free_command(sc, cm); 2919216088Sken ccb->ccb_h.status = CAM_RESRC_UNAVAIL; 2920216088Sken xpt_done(ccb); 2921216088Sken return; 2922216088Sken 2923216088Sken} 2924216088Sken 2925216088Skenstatic void 2926216088Skenmpssas_action_smpio(struct mpssas_softc *sassc, union ccb *ccb) 2927216088Sken{ 2928216088Sken struct mps_softc *sc; 2929216088Sken struct mpssas_target *targ; 2930216088Sken uint64_t sasaddr = 0; 2931216088Sken 2932216088Sken sc = sassc->sc; 2933216088Sken 2934216088Sken /* 2935216088Sken * Make sure the target exists. 2936216088Sken */ 2937216088Sken targ = &sassc->targets[ccb->ccb_h.target_id]; 2938216088Sken if (targ->handle == 0x0) { 2939254938Sken mps_dprint(sc, MPS_ERROR, 2940254938Sken "%s: target %d does not exist!\n", __func__, 2941216088Sken ccb->ccb_h.target_id); 2942216088Sken ccb->ccb_h.status = CAM_SEL_TIMEOUT; 2943216088Sken xpt_done(ccb); 2944216088Sken return; 2945216088Sken } 2946216088Sken 2947216088Sken /* 2948216088Sken * If this device has an embedded SMP target, we'll talk to it 2949216088Sken * directly. 2950216088Sken * figure out what the expander's address is. 2951216088Sken */ 2952216088Sken if ((targ->devinfo & MPI2_SAS_DEVICE_INFO_SMP_TARGET) != 0) 2953216088Sken sasaddr = targ->sasaddr; 2954216088Sken 2955216088Sken /* 2956216088Sken * If we don't have a SAS address for the expander yet, try 2957216088Sken * grabbing it from the page 0x83 information cached in the 2958216088Sken * transport layer for this target. LSI expanders report the 2959216088Sken * expander SAS address as the port-associated SAS address in 2960216088Sken * Inquiry VPD page 0x83. Maxim expanders don't report it in page 2961216088Sken * 0x83. 2962216088Sken * 2963216088Sken * XXX KDM disable this for now, but leave it commented out so that 2964216088Sken * it is obvious that this is another possible way to get the SAS 2965216088Sken * address. 2966216088Sken * 2967216088Sken * The parent handle method below is a little more reliable, and 2968216088Sken * the other benefit is that it works for devices other than SES 2969216088Sken * devices. So you can send a SMP request to a da(4) device and it 2970216088Sken * will get routed to the expander that device is attached to. 2971216088Sken * (Assuming the da(4) device doesn't contain an SMP target...) 2972216088Sken */ 2973216088Sken#if 0 2974216088Sken if (sasaddr == 0) 2975216088Sken sasaddr = xpt_path_sas_addr(ccb->ccb_h.path); 2976216088Sken#endif 2977216088Sken 2978216088Sken /* 2979216088Sken * If we still don't have a SAS address for the expander, look for 2980216088Sken * the parent device of this device, which is probably the expander. 2981216088Sken */ 2982216088Sken if (sasaddr == 0) { 2983230920Sken#ifdef OLD_MPS_PROBE 2984216088Sken struct mpssas_target *parent_target; 2985230920Sken#endif 2986216088Sken 2987216088Sken if (targ->parent_handle == 0x0) { 2988254938Sken mps_dprint(sc, MPS_ERROR, 2989254938Sken "%s: handle %d does not have a valid " 2990216088Sken "parent handle!\n", __func__, targ->handle); 2991216088Sken ccb->ccb_h.status = CAM_REQ_INVALID; 2992216088Sken goto bailout; 2993216088Sken } 2994230920Sken#ifdef OLD_MPS_PROBE 2995230920Sken parent_target = mpssas_find_target_by_handle(sassc, 0, 2996230920Sken targ->parent_handle); 2997216088Sken 2998216088Sken if (parent_target == NULL) { 2999254938Sken mps_dprint(sc, MPS_ERROR, 3000254938Sken "%s: handle %d does not have a valid " 3001216088Sken "parent target!\n", __func__, targ->handle); 3002216088Sken ccb->ccb_h.status = CAM_REQ_INVALID; 3003216088Sken goto bailout; 3004216088Sken } 3005216088Sken 3006216088Sken if ((parent_target->devinfo & 3007216088Sken MPI2_SAS_DEVICE_INFO_SMP_TARGET) == 0) { 3008254938Sken mps_dprint(sc, MPS_ERROR, 3009254938Sken "%s: handle %d parent %d does not " 3010216088Sken "have an SMP target!\n", __func__, 3011216088Sken targ->handle, parent_target->handle); 3012216088Sken ccb->ccb_h.status = CAM_REQ_INVALID; 3013216088Sken goto bailout; 3014216088Sken 3015216088Sken } 3016216088Sken 3017216088Sken sasaddr = parent_target->sasaddr; 3018230920Sken#else /* OLD_MPS_PROBE */ 3019230920Sken if ((targ->parent_devinfo & 3020230920Sken MPI2_SAS_DEVICE_INFO_SMP_TARGET) == 0) { 3021254938Sken mps_dprint(sc, MPS_ERROR, 3022254938Sken "%s: handle %d parent %d does not " 3023230920Sken "have an SMP target!\n", __func__, 3024230920Sken targ->handle, targ->parent_handle); 3025230920Sken ccb->ccb_h.status = CAM_REQ_INVALID; 3026230920Sken goto bailout; 3027230920Sken 3028230920Sken } 3029230920Sken if (targ->parent_sasaddr == 0x0) { 3030254938Sken mps_dprint(sc, MPS_ERROR, 3031254938Sken "%s: handle %d parent handle %d does " 3032230920Sken "not have a valid SAS address!\n", 3033230920Sken __func__, targ->handle, targ->parent_handle); 3034230920Sken ccb->ccb_h.status = CAM_REQ_INVALID; 3035230920Sken goto bailout; 3036230920Sken } 3037230920Sken 3038230920Sken sasaddr = targ->parent_sasaddr; 3039230920Sken#endif /* OLD_MPS_PROBE */ 3040230920Sken 3041216088Sken } 3042216088Sken 3043216088Sken if (sasaddr == 0) { 3044254938Sken mps_dprint(sc, MPS_INFO, 3045254938Sken "%s: unable to find SAS address for handle %d\n", 3046216088Sken __func__, targ->handle); 3047216088Sken ccb->ccb_h.status = CAM_REQ_INVALID; 3048216088Sken goto bailout; 3049216088Sken } 3050216088Sken mpssas_send_smpcmd(sassc, ccb, sasaddr); 3051216088Sken 3052216088Sken return; 3053216088Sken 3054216088Skenbailout: 3055216088Sken xpt_done(ccb); 3056216088Sken 3057216088Sken} 3058230920Sken#endif //__FreeBSD_version >= 900026 3059216088Sken 3060216088Skenstatic void 3061212420Skenmpssas_action_resetdev(struct mpssas_softc *sassc, union ccb *ccb) 3062212420Sken{ 3063230920Sken MPI2_SCSI_TASK_MANAGE_REQUEST *req; 3064212420Sken struct mps_softc *sc; 3065230920Sken struct mps_command *tm; 3066212420Sken struct mpssas_target *targ; 3067212420Sken 3068254938Sken MPS_FUNCTRACE(sassc->sc); 3069230920Sken mtx_assert(&sassc->sc->mps_mtx, MA_OWNED); 3070230920Sken 3071212420Sken sc = sassc->sc; 3072230920Sken tm = mps_alloc_command(sc); 3073230920Sken if (tm == NULL) { 3074254938Sken mps_dprint(sc, MPS_ERROR, 3075256235Smav "command alloc failure in mpssas_action_resetdev\n"); 3076212420Sken ccb->ccb_h.status = CAM_RESRC_UNAVAIL; 3077212420Sken xpt_done(ccb); 3078212420Sken return; 3079212420Sken } 3080212420Sken 3081230920Sken targ = &sassc->targets[ccb->ccb_h.target_id]; 3082230920Sken req = (MPI2_SCSI_TASK_MANAGE_REQUEST *)tm->cm_req; 3083237876Sken req->DevHandle = htole16(targ->handle); 3084212420Sken req->Function = MPI2_FUNCTION_SCSI_TASK_MGMT; 3085212420Sken req->TaskType = MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET; 3086212420Sken 3087212420Sken /* SAS Hard Link Reset / SATA Link Reset */ 3088212420Sken req->MsgFlags = MPI2_SCSITASKMGMT_MSGFLAGS_LINK_RESET; 3089212420Sken 3090230920Sken tm->cm_data = NULL; 3091230920Sken tm->cm_desc.HighPriority.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_HIGH_PRIORITY; 3092230920Sken tm->cm_complete = mpssas_resetdev_complete; 3093230920Sken tm->cm_complete_data = ccb; 3094239415Smav tm->cm_targ = targ; 3095230920Sken mps_map_command(sc, tm); 3096212420Sken} 3097212420Sken 3098212420Skenstatic void 3099230920Skenmpssas_resetdev_complete(struct mps_softc *sc, struct mps_command *tm) 3100212420Sken{ 3101212420Sken MPI2_SCSI_TASK_MANAGE_REPLY *resp; 3102212420Sken union ccb *ccb; 3103212420Sken 3104254938Sken MPS_FUNCTRACE(sc); 3105230920Sken mtx_assert(&sc->mps_mtx, MA_OWNED); 3106212420Sken 3107230920Sken resp = (MPI2_SCSI_TASK_MANAGE_REPLY *)tm->cm_reply; 3108230920Sken ccb = tm->cm_complete_data; 3109212420Sken 3110230920Sken /* 3111230920Sken * Currently there should be no way we can hit this case. It only 3112230920Sken * happens when we have a failure to allocate chain frames, and 3113230920Sken * task management commands don't have S/G lists. 3114230920Sken */ 3115230920Sken if ((tm->cm_flags & MPS_CM_FLAGS_ERROR_MASK) != 0) { 3116218812Sken MPI2_SCSI_TASK_MANAGE_REQUEST *req; 3117218812Sken 3118230920Sken req = (MPI2_SCSI_TASK_MANAGE_REQUEST *)tm->cm_req; 3119218812Sken 3120254938Sken mps_dprint(sc, MPS_ERROR, 3121254938Sken "%s: cm_flags = %#x for reset of handle %#04x! " 3122230920Sken "This should not happen!\n", __func__, tm->cm_flags, 3123218812Sken req->DevHandle); 3124218812Sken ccb->ccb_h.status = CAM_REQ_CMP_ERR; 3125218812Sken goto bailout; 3126218812Sken } 3127218812Sken 3128254938Sken mps_dprint(sc, MPS_XINFO, 3129254938Sken "%s: IOCStatus = 0x%x ResponseCode = 0x%x\n", __func__, 3130237876Sken le16toh(resp->IOCStatus), le32toh(resp->ResponseCode)); 3131212420Sken 3132237876Sken if (le32toh(resp->ResponseCode) == MPI2_SCSITASKMGMT_RSP_TM_COMPLETE) { 3133212420Sken ccb->ccb_h.status = CAM_REQ_CMP; 3134230920Sken mpssas_announce_reset(sc, AC_SENT_BDR, tm->cm_targ->tid, 3135230920Sken CAM_LUN_WILDCARD); 3136230920Sken } 3137212420Sken else 3138212420Sken ccb->ccb_h.status = CAM_REQ_CMP_ERR; 3139212420Sken 3140218812Skenbailout: 3141212772Sken 3142230920Sken mpssas_free_tm(sc, tm); 3143212420Sken xpt_done(ccb); 3144212420Sken} 3145212420Sken 3146212420Skenstatic void 3147212420Skenmpssas_poll(struct cam_sim *sim) 3148212420Sken{ 3149212420Sken struct mpssas_softc *sassc; 3150212420Sken 3151212420Sken sassc = cam_sim_softc(sim); 3152230920Sken 3153230920Sken if (sassc->sc->mps_debug & MPS_TRACE) { 3154230920Sken /* frequent debug messages during a panic just slow 3155230920Sken * everything down too much. 3156230920Sken */ 3157230920Sken mps_printf(sassc->sc, "%s clearing MPS_TRACE\n", __func__); 3158230920Sken sassc->sc->mps_debug &= ~MPS_TRACE; 3159230920Sken } 3160230920Sken 3161212420Sken mps_intr_locked(sassc->sc); 3162212420Sken} 3163212420Sken 3164212420Skenstatic void 3165230920Skenmpssas_async(void *callback_arg, uint32_t code, struct cam_path *path, 3166230920Sken void *arg) 3167230920Sken{ 3168230920Sken struct mps_softc *sc; 3169230920Sken 3170230920Sken sc = (struct mps_softc *)callback_arg; 3171230920Sken 3172230920Sken switch (code) { 3173254938Sken#if (__FreeBSD_version >= 1000006) || \ 3174254938Sken ((__FreeBSD_version >= 901503) && (__FreeBSD_version < 1000000)) 3175230920Sken case AC_ADVINFO_CHANGED: { 3176230920Sken struct mpssas_target *target; 3177230920Sken struct mpssas_softc *sassc; 3178230920Sken struct scsi_read_capacity_data_long rcap_buf; 3179230920Sken struct ccb_dev_advinfo cdai; 3180230920Sken struct mpssas_lun *lun; 3181230920Sken lun_id_t lunid; 3182230920Sken int found_lun; 3183230920Sken uintptr_t buftype; 3184230920Sken 3185230920Sken buftype = (uintptr_t)arg; 3186230920Sken 3187230920Sken found_lun = 0; 3188230920Sken sassc = sc->sassc; 3189230920Sken 3190230920Sken /* 3191230920Sken * We're only interested in read capacity data changes. 3192230920Sken */ 3193230920Sken if (buftype != CDAI_TYPE_RCAPLONG) 3194230920Sken break; 3195230920Sken 3196230920Sken /* 3197230920Sken * We should have a handle for this, but check to make sure. 3198230920Sken */ 3199230920Sken target = &sassc->targets[xpt_path_target_id(path)]; 3200230920Sken if (target->handle == 0) 3201230920Sken break; 3202230920Sken 3203230920Sken lunid = xpt_path_lun_id(path); 3204230920Sken 3205230920Sken SLIST_FOREACH(lun, &target->luns, lun_link) { 3206230920Sken if (lun->lun_id == lunid) { 3207230920Sken found_lun = 1; 3208230920Sken break; 3209230920Sken } 3210230920Sken } 3211230920Sken 3212230920Sken if (found_lun == 0) { 3213230920Sken lun = malloc(sizeof(struct mpssas_lun), M_MPT2, 3214230920Sken M_NOWAIT | M_ZERO); 3215230920Sken if (lun == NULL) { 3216254938Sken mps_dprint(sc, MPS_ERROR, "Unable to alloc " 3217230920Sken "LUN for EEDP support.\n"); 3218230920Sken break; 3219230920Sken } 3220230920Sken lun->lun_id = lunid; 3221230920Sken SLIST_INSERT_HEAD(&target->luns, lun, lun_link); 3222230920Sken } 3223230920Sken 3224230920Sken bzero(&rcap_buf, sizeof(rcap_buf)); 3225230920Sken xpt_setup_ccb(&cdai.ccb_h, path, CAM_PRIORITY_NORMAL); 3226230920Sken cdai.ccb_h.func_code = XPT_DEV_ADVINFO; 3227230920Sken cdai.ccb_h.flags = CAM_DIR_IN; 3228230920Sken cdai.buftype = CDAI_TYPE_RCAPLONG; 3229230920Sken cdai.flags = 0; 3230230920Sken cdai.bufsiz = sizeof(rcap_buf); 3231230920Sken cdai.buf = (uint8_t *)&rcap_buf; 3232230920Sken xpt_action((union ccb *)&cdai); 3233230920Sken if ((cdai.ccb_h.status & CAM_DEV_QFRZN) != 0) 3234230920Sken cam_release_devq(cdai.ccb_h.path, 3235230920Sken 0, 0, 0, FALSE); 3236230920Sken 3237230920Sken if (((cdai.ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP) 3238230920Sken && (rcap_buf.prot & SRC16_PROT_EN)) { 3239230920Sken lun->eedp_formatted = TRUE; 3240230920Sken lun->eedp_block_size = scsi_4btoul(rcap_buf.length); 3241230920Sken } else { 3242230920Sken lun->eedp_formatted = FALSE; 3243230920Sken lun->eedp_block_size = 0; 3244230920Sken } 3245230920Sken break; 3246230920Sken } 3247254938Sken#else 3248254938Sken case AC_FOUND_DEVICE: { 3249254938Sken struct ccb_getdev *cgd; 3250254938Sken 3251254938Sken cgd = arg; 3252254938Sken mpssas_check_eedp(sc, path, cgd); 3253254938Sken break; 3254254938Sken } 3255254938Sken#endif 3256230920Sken default: 3257230920Sken break; 3258230920Sken } 3259230920Sken} 3260230920Sken 3261254938Sken#if (__FreeBSD_version < 901503) || \ 3262254938Sken ((__FreeBSD_version >= 1000000) && (__FreeBSD_version < 1000006)) 3263230920Skenstatic void 3264254938Skenmpssas_check_eedp(struct mps_softc *sc, struct cam_path *path, 3265254938Sken struct ccb_getdev *cgd) 3266230920Sken{ 3267254938Sken struct mpssas_softc *sassc = sc->sassc; 3268230920Sken struct ccb_scsiio *csio; 3269230920Sken struct scsi_read_capacity_16 *scsi_cmd; 3270230920Sken struct scsi_read_capacity_eedp *rcap_buf; 3271254938Sken path_id_t pathid; 3272230920Sken target_id_t targetid; 3273230920Sken lun_id_t lunid; 3274254938Sken union ccb *ccb; 3275254938Sken struct cam_path *local_path; 3276230920Sken struct mpssas_target *target; 3277230920Sken struct mpssas_lun *lun; 3278230920Sken uint8_t found_lun; 3279237876Sken char path_str[64]; 3280230920Sken 3281254938Sken sassc = sc->sassc; 3282254938Sken pathid = cam_sim_path(sassc->sim); 3283254938Sken targetid = xpt_path_target_id(path); 3284254938Sken lunid = xpt_path_lun_id(path); 3285254938Sken 3286254938Sken target = &sassc->targets[targetid]; 3287254938Sken if (target->handle == 0x0) 3288254938Sken return; 3289254938Sken 3290230920Sken /* 3291254938Sken * Determine if the device is EEDP capable. 3292254938Sken * 3293254938Sken * If this flag is set in the inquiry data, 3294254938Sken * the device supports protection information, 3295254938Sken * and must support the 16 byte read 3296254938Sken * capacity command, otherwise continue without 3297254938Sken * sending read cap 16 3298230920Sken */ 3299254938Sken if ((cgd->inq_data.spc3_flags & SPC3_SID_PROTECT) == 0) 3300254938Sken return; 3301230920Sken 3302254938Sken /* 3303254938Sken * Issue a READ CAPACITY 16 command. This info 3304254938Sken * is used to determine if the LUN is formatted 3305254938Sken * for EEDP support. 3306254938Sken */ 3307254938Sken ccb = xpt_alloc_ccb_nowait(); 3308254938Sken if (ccb == NULL) { 3309254938Sken mps_dprint(sc, MPS_ERROR, "Unable to alloc CCB " 3310254938Sken "for EEDP support.\n"); 3311254938Sken return; 3312254938Sken } 3313230920Sken 3314254938Sken if (xpt_create_path(&local_path, xpt_periph, 3315254938Sken pathid, targetid, lunid) != CAM_REQ_CMP) { 3316254938Sken mps_dprint(sc, MPS_ERROR, "Unable to create " 3317254938Sken "path for EEDP support\n"); 3318254938Sken xpt_free_ccb(ccb); 3319254938Sken return; 3320254938Sken } 3321230920Sken 3322254938Sken /* 3323254938Sken * If LUN is already in list, don't create a new 3324254938Sken * one. 3325254938Sken */ 3326254938Sken found_lun = FALSE; 3327254938Sken SLIST_FOREACH(lun, &target->luns, lun_link) { 3328254938Sken if (lun->lun_id == lunid) { 3329254938Sken found_lun = TRUE; 3330254938Sken break; 3331254938Sken } 3332254938Sken } 3333254938Sken if (!found_lun) { 3334254938Sken lun = malloc(sizeof(struct mpssas_lun), M_MPT2, 3335254938Sken M_NOWAIT | M_ZERO); 3336254938Sken if (lun == NULL) { 3337254938Sken mps_dprint(sc, MPS_ERROR, 3338254938Sken "Unable to alloc LUN for EEDP support.\n"); 3339254938Sken xpt_free_path(local_path); 3340254938Sken xpt_free_ccb(ccb); 3341254938Sken return; 3342254938Sken } 3343254938Sken lun->lun_id = lunid; 3344254938Sken SLIST_INSERT_HEAD(&target->luns, lun, 3345254938Sken lun_link); 3346254938Sken } 3347230920Sken 3348254938Sken xpt_path_string(local_path, path_str, sizeof(path_str)); 3349254938Sken mps_dprint(sc, MPS_INFO, "Sending read cap: path %s handle %d\n", 3350254938Sken path_str, target->handle); 3351237876Sken 3352254938Sken /* 3353254938Sken * Issue a READ CAPACITY 16 command for the LUN. 3354254938Sken * The mpssas_read_cap_done function will load 3355254938Sken * the read cap info into the LUN struct. 3356254938Sken */ 3357254938Sken rcap_buf = malloc(sizeof(struct scsi_read_capacity_eedp), 3358254938Sken M_MPT2, M_NOWAIT | M_ZERO); 3359254938Sken if (rcap_buf == NULL) { 3360254938Sken mps_dprint(sc, MPS_FAULT, 3361254938Sken "Unable to alloc read capacity buffer for EEDP support.\n"); 3362254938Sken xpt_free_path(ccb->ccb_h.path); 3363254938Sken xpt_free_ccb(ccb); 3364254938Sken return; 3365254938Sken } 3366254938Sken xpt_setup_ccb(&ccb->ccb_h, local_path, CAM_PRIORITY_XPT); 3367254938Sken csio = &ccb->csio; 3368254938Sken csio->ccb_h.func_code = XPT_SCSI_IO; 3369254938Sken csio->ccb_h.flags = CAM_DIR_IN; 3370254938Sken csio->ccb_h.retry_count = 4; 3371254938Sken csio->ccb_h.cbfcnp = mpssas_read_cap_done; 3372254938Sken csio->ccb_h.timeout = 60000; 3373254938Sken csio->data_ptr = (uint8_t *)rcap_buf; 3374254938Sken csio->dxfer_len = sizeof(struct scsi_read_capacity_eedp); 3375254938Sken csio->sense_len = MPS_SENSE_LEN; 3376254938Sken csio->cdb_len = sizeof(*scsi_cmd); 3377254938Sken csio->tag_action = MSG_SIMPLE_Q_TAG; 3378237876Sken 3379254938Sken scsi_cmd = (struct scsi_read_capacity_16 *)&csio->cdb_io.cdb_bytes; 3380254938Sken bzero(scsi_cmd, sizeof(*scsi_cmd)); 3381254938Sken scsi_cmd->opcode = 0x9E; 3382254938Sken scsi_cmd->service_action = SRC16_SERVICE_ACTION; 3383254938Sken ((uint8_t *)scsi_cmd)[13] = sizeof(struct scsi_read_capacity_eedp); 3384230920Sken 3385254938Sken ccb->ccb_h.ppriv_ptr1 = sassc; 3386254938Sken xpt_action(ccb); 3387230920Sken} 3388230920Sken 3389230920Skenstatic void 3390230920Skenmpssas_read_cap_done(struct cam_periph *periph, union ccb *done_ccb) 3391230920Sken{ 3392230920Sken struct mpssas_softc *sassc; 3393230920Sken struct mpssas_target *target; 3394230920Sken struct mpssas_lun *lun; 3395230920Sken struct scsi_read_capacity_eedp *rcap_buf; 3396230920Sken 3397230920Sken if (done_ccb == NULL) 3398230920Sken return; 3399231679Sken 3400231679Sken /* Driver need to release devq, it Scsi command is 3401231679Sken * generated by driver internally. 3402231679Sken * Currently there is a single place where driver 3403231679Sken * calls scsi command internally. In future if driver 3404231679Sken * calls more scsi command internally, it needs to release 3405231679Sken * devq internally, since those command will not go back to 3406231679Sken * cam_periph. 3407231679Sken */ 3408231679Sken if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) ) { 3409231679Sken done_ccb->ccb_h.status &= ~CAM_DEV_QFRZN; 3410231679Sken xpt_release_devq(done_ccb->ccb_h.path, 3411231679Sken /*count*/ 1, /*run_queue*/TRUE); 3412231679Sken } 3413230920Sken 3414230920Sken rcap_buf = (struct scsi_read_capacity_eedp *)done_ccb->csio.data_ptr; 3415230920Sken 3416230920Sken /* 3417230920Sken * Get the LUN ID for the path and look it up in the LUN list for the 3418230920Sken * target. 3419230920Sken */ 3420230920Sken sassc = (struct mpssas_softc *)done_ccb->ccb_h.ppriv_ptr1; 3421230920Sken target = &sassc->targets[done_ccb->ccb_h.target_id]; 3422230920Sken SLIST_FOREACH(lun, &target->luns, lun_link) { 3423230920Sken if (lun->lun_id != done_ccb->ccb_h.target_lun) 3424230920Sken continue; 3425230920Sken 3426230920Sken /* 3427230920Sken * Got the LUN in the target's LUN list. Fill it in 3428230920Sken * with EEDP info. If the READ CAP 16 command had some 3429230920Sken * SCSI error (common if command is not supported), mark 3430230920Sken * the lun as not supporting EEDP and set the block size 3431230920Sken * to 0. 3432230920Sken */ 3433230920Sken if (((done_ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) 3434230920Sken || (done_ccb->csio.scsi_status != SCSI_STATUS_OK)) { 3435230920Sken lun->eedp_formatted = FALSE; 3436230920Sken lun->eedp_block_size = 0; 3437230920Sken break; 3438230920Sken } 3439230920Sken 3440230920Sken if (rcap_buf->protect & 0x01) { 3441254938Sken mps_dprint(sassc->sc, MPS_INFO, "LUN %d for " 3442254938Sken "target ID %d is formatted for EEDP " 3443254938Sken "support.\n", done_ccb->ccb_h.target_lun, 3444254938Sken done_ccb->ccb_h.target_id); 3445230920Sken lun->eedp_formatted = TRUE; 3446230920Sken lun->eedp_block_size = scsi_4btoul(rcap_buf->length); 3447230920Sken } 3448230920Sken break; 3449230920Sken } 3450230920Sken 3451230920Sken // Finished with this CCB and path. 3452230920Sken free(rcap_buf, M_MPT2); 3453230920Sken xpt_free_path(done_ccb->ccb_h.path); 3454230920Sken xpt_free_ccb(done_ccb); 3455230920Sken} 3456254938Sken#endif /* (__FreeBSD_version < 901503) || \ 3457254938Sken ((__FreeBSD_version >= 1000000) && (__FreeBSD_version < 1000006)) */ 3458230920Sken 3459230920Skenint 3460230920Skenmpssas_startup(struct mps_softc *sc) 3461230920Sken{ 3462230920Sken 3463230920Sken /* 3464230920Sken * Send the port enable message and set the wait_for_port_enable flag. 3465230920Sken * This flag helps to keep the simq frozen until all discovery events 3466230920Sken * are processed. 3467230920Sken */ 3468230920Sken sc->wait_for_port_enable = 1; 3469230920Sken mpssas_send_portenable(sc); 3470230920Sken return (0); 3471230920Sken} 3472230920Sken 3473230920Skenstatic int 3474230920Skenmpssas_send_portenable(struct mps_softc *sc) 3475230920Sken{ 3476230920Sken MPI2_PORT_ENABLE_REQUEST *request; 3477230920Sken struct mps_command *cm; 3478230920Sken 3479254938Sken MPS_FUNCTRACE(sc); 3480230920Sken 3481230920Sken if ((cm = mps_alloc_command(sc)) == NULL) 3482230920Sken return (EBUSY); 3483230920Sken request = (MPI2_PORT_ENABLE_REQUEST *)cm->cm_req; 3484230920Sken request->Function = MPI2_FUNCTION_PORT_ENABLE; 3485230920Sken request->MsgFlags = 0; 3486230920Sken request->VP_ID = 0; 3487230920Sken cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 3488230920Sken cm->cm_complete = mpssas_portenable_complete; 3489230920Sken cm->cm_data = NULL; 3490230920Sken cm->cm_sge = NULL; 3491230920Sken 3492230920Sken mps_map_command(sc, cm); 3493254938Sken mps_dprint(sc, MPS_XINFO, 3494230920Sken "mps_send_portenable finished cm %p req %p complete %p\n", 3495230920Sken cm, cm->cm_req, cm->cm_complete); 3496230920Sken return (0); 3497230920Sken} 3498230920Sken 3499230920Skenstatic void 3500230920Skenmpssas_portenable_complete(struct mps_softc *sc, struct mps_command *cm) 3501230920Sken{ 3502230920Sken MPI2_PORT_ENABLE_REPLY *reply; 3503230920Sken struct mpssas_softc *sassc; 3504230920Sken 3505254938Sken MPS_FUNCTRACE(sc); 3506230920Sken sassc = sc->sassc; 3507230920Sken 3508230920Sken /* 3509230920Sken * Currently there should be no way we can hit this case. It only 3510230920Sken * happens when we have a failure to allocate chain frames, and 3511230920Sken * port enable commands don't have S/G lists. 3512230920Sken */ 3513230920Sken if ((cm->cm_flags & MPS_CM_FLAGS_ERROR_MASK) != 0) { 3514254938Sken mps_dprint(sc, MPS_ERROR, "%s: cm_flags = %#x for port enable! " 3515230920Sken "This should not happen!\n", __func__, cm->cm_flags); 3516230920Sken } 3517230920Sken 3518230920Sken reply = (MPI2_PORT_ENABLE_REPLY *)cm->cm_reply; 3519230920Sken if (reply == NULL) 3520230920Sken mps_dprint(sc, MPS_FAULT, "Portenable NULL reply\n"); 3521237876Sken else if (le16toh(reply->IOCStatus & MPI2_IOCSTATUS_MASK) != 3522230920Sken MPI2_IOCSTATUS_SUCCESS) 3523230920Sken mps_dprint(sc, MPS_FAULT, "Portenable failed\n"); 3524230920Sken 3525230920Sken mps_free_command(sc, cm); 3526230920Sken if (sc->mps_ich.ich_arg != NULL) { 3527254938Sken mps_dprint(sc, MPS_XINFO, "disestablish config intrhook\n"); 3528230920Sken config_intrhook_disestablish(&sc->mps_ich); 3529230920Sken sc->mps_ich.ich_arg = NULL; 3530230920Sken } 3531230920Sken 3532230920Sken /* 3533230920Sken * Get WarpDrive info after discovery is complete but before the scan 3534230920Sken * starts. At this point, all devices are ready to be exposed to the 3535230920Sken * OS. If devices should be hidden instead, take them out of the 3536230920Sken * 'targets' array before the scan. The devinfo for a disk will have 3537230920Sken * some info and a volume's will be 0. Use that to remove disks. 3538230920Sken */ 3539230920Sken mps_wd_config_pages(sc); 3540230920Sken 3541230920Sken /* 3542230920Sken * Done waiting for port enable to complete. Decrement the refcount. 3543230920Sken * If refcount is 0, discovery is complete and a rescan of the bus can 3544230920Sken * take place. Since the simq was explicitly frozen before port 3545230920Sken * enable, it must be explicitly released here to keep the 3546230920Sken * freeze/release count in sync. 3547230920Sken */ 3548230920Sken sc->wait_for_port_enable = 0; 3549230920Sken sc->port_enable_complete = 1; 3550237876Sken wakeup(&sc->port_enable_complete); 3551230920Sken mpssas_startup_decrement(sassc); 3552230920Sken} 3553230920Sken 3554