Date: Mon, 12 Aug 2013 13:02:29 -0600 From: "Kenneth D. Merry" <ken@FreeBSD.org> To: Slawa Olhovchenkov <slw@zxy.spb.ru> Cc: svn-src-head@FreeBSD.org, svn-src-all@FreeBSD.org, src-committers@FreeBSD.org Subject: Re: svn commit: r253550 - head/sys/dev/mps Message-ID: <20130812190229.GA24478@nargothrond.kdm.org> In-Reply-To: <20130812174545.GA3796@zxy.spb.ru> References: <201307221841.r6MIfsoQ075667@svn.freebsd.org> <20130810181454.GA47115@zxy.spb.ru> <20130812155647.GA11414@nargothrond.kdm.org> <20130812174545.GA3796@zxy.spb.ru>
next in thread | previous in thread | raw e-mail | index | archive | help
--k1lZvvs/B4yU6o8G Content-Type: text/plain; charset=us-ascii Content-Disposition: inline On Mon, Aug 12, 2013 at 21:45:45 +0400, Slawa Olhovchenkov wrote: > On Mon, Aug 12, 2013 at 09:56:48AM -0600, Kenneth D. Merry wrote: > > > On Sat, Aug 10, 2013 at 22:14:54 +0400, Slawa Olhovchenkov wrote: > > > On Mon, Jul 22, 2013 at 06:41:54PM +0000, Kenneth D. Merry wrote: > > > > > > > Author: ken > > > > Date: Mon Jul 22 18:41:53 2013 > > > > New Revision: 253550 > > > > URL: http://svnweb.freebsd.org/changeset/base/253550 > > > > > > > > Log: > > > > Merge in phase 14+ -> 16 mps driver fixes from LSI: > > > > Submitted by: LSI > > > > MFC after: 1 week > > > > > > Not done? > > > > I was waiting for the stable/9 freeze to end. > > Hm? > > Date: Mon Aug 5 23:34:35 2013 > New Revision: 253975 > URL: http://svnweb.freebsd.org/changeset/base/253975 > > Log: > stable/9 no longer requires re@ approval for commits, now that the > releng/9.2 branch is created. > > Committers are urged to exercise caution with commits to stable/9 > until the 9.2-RELEASE is finalized. > > Or, can you published patch for 9-STABLE? If you really want one now, I've attached a patch from stable/9 on June 27th. It may or may not apply now. > > Now that it's done, I hope to merge that change to stable/9 this week. > > Also, I see strange behaviour of LSI 9211-8i -- after some activity > got timeout and HBA put in looped reset. That's not good. Try with the newer driver and see whether if affects the behavior. Ken -- Kenneth Merry ken@FreeBSD.ORG --k1lZvvs/B4yU6o8G Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename="mps_scan_stable9.20130627.1.txt" *** src/sys/cam/cam_ccb.h.orig --- src/sys/cam/cam_ccb.h *************** *** 578,583 **** --- 578,584 ---- PIM_NO_6_BYTE = 0x08, /* Do not send 6-byte commands */ PIM_SEQSCAN = 0x04, /* Do bus scans sequentially, not in parallel */ PIM_UNMAPPED = 0x02, + PIM_NOSCAN = 0x01 /* SIM does its own scanning */ } pi_miscflag; /* Path Inquiry CCB */ *** src/sys/cam/cam_xpt.c.orig --- src/sys/cam/cam_xpt.c *************** *** 4012,4026 **** /* Notify interested parties */ if (sim->path_id != CAM_XPT_PATH_ID) { - union ccb *scan_ccb; xpt_async(AC_PATH_REGISTERED, path, &cpi); ! /* Initiate bus rescan. */ ! scan_ccb = xpt_alloc_ccb_nowait(); ! scan_ccb->ccb_h.path = path; ! scan_ccb->ccb_h.func_code = XPT_SCAN_BUS; ! scan_ccb->crcn.flags = 0; ! xpt_rescan(scan_ccb); } else xpt_free_path(path); return (CAM_SUCCESS); --- 4012,4030 ---- /* Notify interested parties */ if (sim->path_id != CAM_XPT_PATH_ID) { xpt_async(AC_PATH_REGISTERED, path, &cpi); ! ! if ((cpi.hba_misc & PIM_NOSCAN) == 0) { ! union ccb *scan_ccb; ! ! /* Initiate bus rescan. */ ! scan_ccb = xpt_alloc_ccb_nowait(); ! scan_ccb->ccb_h.path = path; ! scan_ccb->ccb_h.func_code = XPT_SCAN_BUS; ! scan_ccb->crcn.flags = 0; ! xpt_rescan(scan_ccb); ! } } else xpt_free_path(path); return (CAM_SUCCESS); *** src/sys/dev/mps/mps.c.orig --- src/sys/dev/mps/mps.c *************** *** 51,56 **** --- 51,57 ---- #include <sys/sysctl.h> #include <sys/queue.h> #include <sys/kthread.h> + #include <sys/taskqueue.h> #include <sys/endian.h> #include <sys/eventhandler.h> *************** *** 61,66 **** --- 62,68 ---- #include <dev/pci/pcivar.h> + #include <cam/cam.h> #include <cam/scsi/scsi_all.h> #include <dev/mps/mpi/mpi2_type.h> *************** *** 73,85 **** --- 75,93 ---- #include <dev/mps/mps_ioctl.h> #include <dev/mps/mpsvar.h> #include <dev/mps/mps_table.h> + #include <dev/mps/mps_sas.h> static int mps_diag_reset(struct mps_softc *sc, int sleep_flag); static int mps_init_queues(struct mps_softc *sc); static int mps_message_unit_reset(struct mps_softc *sc, int sleep_flag); static int mps_transition_operational(struct mps_softc *sc); + static int mps_iocfacts_allocate(struct mps_softc *sc, uint8_t attaching); + static void mps_iocfacts_free(struct mps_softc *sc); static void mps_startup(void *arg); static int mps_send_iocinit(struct mps_softc *sc); + static int mps_alloc_queues(struct mps_softc *sc); + static int mps_alloc_replies(struct mps_softc *sc); + static int mps_alloc_requests(struct mps_softc *sc); static int mps_attach_log(struct mps_softc *sc); static __inline void mps_complete_command(struct mps_command *cm); static void mps_dispatch_event(struct mps_softc *sc, uintptr_t data, *************** *** 88,93 **** --- 96,102 ---- static void mps_periodic(void *); static int mps_reregister_events(struct mps_softc *sc); static void mps_enqueue_request(struct mps_softc *sc, struct mps_command *cm); + static int mps_get_iocfacts(struct mps_softc *sc, MPI2_IOC_FACTS_REPLY *facts); static int mps_wait_db_ack(struct mps_softc *sc, int timeout, int sleep_flag); SYSCTL_NODE(_hw, OID_AUTO, mps, CTLFLAG_RD, 0, "MPS Driver Parameters"); *************** *** 148,154 **** mpt2_reset_magic[i]); /* wait 100 msec */ if (mtx_owned(&sc->mps_mtx) && sleep_flag == CAN_SLEEP) ! msleep(&sc->msleep_fake_chan, &sc->mps_mtx, 0, "mpsdiag", hz/10); else if (sleep_flag == CAN_SLEEP) pause("mpsdiag", hz/10); else --- 157,164 ---- mpt2_reset_magic[i]); /* wait 100 msec */ if (mtx_owned(&sc->mps_mtx) && sleep_flag == CAN_SLEEP) ! msleep(&sc->msleep_fake_chan, &sc->mps_mtx, 0, ! "mpsdiag", hz/10); else if (sleep_flag == CAN_SLEEP) pause("mpsdiag", hz/10); else *************** *** 172,178 **** for (i = 0; i < 60000; i++) { /* wait 50 msec */ if (mtx_owned(&sc->mps_mtx) && sleep_flag == CAN_SLEEP) ! msleep(&sc->msleep_fake_chan, &sc->mps_mtx, 0, "mpsdiag", hz/20); else if (sleep_flag == CAN_SLEEP) pause("mpsdiag", hz/20); else --- 182,189 ---- for (i = 0; i < 60000; i++) { /* wait 50 msec */ if (mtx_owned(&sc->mps_mtx) && sleep_flag == CAN_SLEEP) ! msleep(&sc->msleep_fake_chan, &sc->mps_mtx, 0, ! "mpsdiag", hz/20); else if (sleep_flag == CAN_SLEEP) pause("mpsdiag", hz/20); else *************** *** 302,310 **** return (error); } /* - * XXX Some of this should probably move to mps.c - * * The terms diag reset and hard reset are used interchangeably in the MPI * docs to mean resetting the controller chip. In this code diag reset * cleans everything up, and the hard reset function just sends the reset --- 313,669 ---- return (error); } + /* + * This is called during attach and when re-initializing due to a Diag Reset. + * IOC Facts is used to allocate many of the structures needed by the driver. + * If called from attach, de-allocation is not required because the driver has + * not allocated any structures yet, but if called from a Diag Reset, previously + * allocated structures based on IOC Facts will need to be freed and re- + * allocated bases on the latest IOC Facts. + */ + static int + mps_iocfacts_allocate(struct mps_softc *sc, uint8_t attaching) + { + int error, i; + Mpi2IOCFactsReply_t saved_facts; + uint8_t saved_mode, reallocating; + struct mpssas_lun *lun, *lun_tmp; + struct mpssas_target *targ; + + mps_dprint(sc, MPS_TRACE, "%s\n", __func__); + + /* Save old IOC Facts and then only reallocate if Facts have changed */ + if (!attaching) { + bcopy(sc->facts, &saved_facts, sizeof(MPI2_IOC_FACTS_REPLY)); + } + + /* + * Get IOC Facts. In all cases throughout this function, panic if doing + * a re-initialization and only return the error if attaching so the OS + * can handle it. + */ + if ((error = mps_get_iocfacts(sc, sc->facts)) != 0) { + if (attaching) { + mps_dprint(sc, MPS_FAULT, "%s failed to get IOC Facts " + "with error %d\n", __func__, error); + return (error); + } else { + panic("%s failed to get IOC Facts with error %d\n", + __func__, error); + } + } + + mps_print_iocfacts(sc, sc->facts); + + snprintf(sc->fw_version, sizeof(sc->fw_version), + "%02d.%02d.%02d.%02d", + sc->facts->FWVersion.Struct.Major, + sc->facts->FWVersion.Struct.Minor, + sc->facts->FWVersion.Struct.Unit, + sc->facts->FWVersion.Struct.Dev); + + mps_printf(sc, "Firmware: %s, Driver: %s\n", sc->fw_version, + MPS_DRIVER_VERSION); + mps_printf(sc, "IOCCapabilities: %b\n", sc->facts->IOCCapabilities, + "\20" "\3ScsiTaskFull" "\4DiagTrace" "\5SnapBuf" "\6ExtBuf" + "\7EEDP" "\10BiDirTarg" "\11Multicast" "\14TransRetry" "\15IR" + "\16EventReplay" "\17RaidAccel" "\20MSIXIndex" "\21HostDisc"); + + /* + * If the chip doesn't support event replay then a hard reset will be + * required to trigger a full discovery. Do the reset here then + * retransition to Ready. A hard reset might have already been done, + * but it doesn't hurt to do it again. Only do this if attaching, not + * for a Diag Reset. + */ + if (attaching) { + if ((sc->facts->IOCCapabilities & + MPI2_IOCFACTS_CAPABILITY_EVENT_REPLAY) == 0) { + mps_diag_reset(sc, NO_SLEEP); + if ((error = mps_transition_ready(sc)) != 0) { + mps_dprint(sc, MPS_FAULT, "%s failed to " + "transition to ready with error %d\n", + __func__, error); + return (error); + } + } + } + + /* + * Set flag if IR Firmware is loaded. If the RAID Capability has + * changed from the previous IOC Facts, log a warning, but only if + * checking this after a Diag Reset and not during attach. + */ + saved_mode = sc->ir_firmware; + if (sc->facts->IOCCapabilities & + MPI2_IOCFACTS_CAPABILITY_INTEGRATED_RAID) + sc->ir_firmware = 1; + if (!attaching) { + if (sc->ir_firmware != saved_mode) { + mps_dprint(sc, MPS_FAULT, "%s new IR/IT mode in IOC " + "Facts does not match previous mode\n", __func__); + } + } + + /* Only deallocate and reallocate if relevant IOC Facts have changed */ + reallocating = FALSE; + if ((!attaching) && + ((saved_facts.MsgVersion != sc->facts->MsgVersion) || + (saved_facts.HeaderVersion != sc->facts->HeaderVersion) || + (saved_facts.MaxChainDepth != sc->facts->MaxChainDepth) || + (saved_facts.RequestCredit != sc->facts->RequestCredit) || + (saved_facts.ProductID != sc->facts->ProductID) || + (saved_facts.IOCCapabilities != sc->facts->IOCCapabilities) || + (saved_facts.IOCRequestFrameSize != + sc->facts->IOCRequestFrameSize) || + (saved_facts.MaxTargets != sc->facts->MaxTargets) || + (saved_facts.MaxSasExpanders != sc->facts->MaxSasExpanders) || + (saved_facts.MaxEnclosures != sc->facts->MaxEnclosures) || + (saved_facts.HighPriorityCredit != sc->facts->HighPriorityCredit) || + (saved_facts.MaxReplyDescriptorPostQueueDepth != + sc->facts->MaxReplyDescriptorPostQueueDepth) || + (saved_facts.ReplyFrameSize != sc->facts->ReplyFrameSize) || + (saved_facts.MaxVolumes != sc->facts->MaxVolumes) || + (saved_facts.MaxPersistentEntries != + sc->facts->MaxPersistentEntries))) { + reallocating = TRUE; + } + + /* + * Some things should be done if attaching or re-allocating after a Diag + * Reset, but are not needed after a Diag Reset if the FW has not + * changed. + */ + if (attaching || reallocating) { + /* + * Check if controller supports FW diag buffers and set flag to + * enable each type. + */ + if (sc->facts->IOCCapabilities & + MPI2_IOCFACTS_CAPABILITY_DIAG_TRACE_BUFFER) + sc->fw_diag_buffer_list[MPI2_DIAG_BUF_TYPE_TRACE]. + enabled = TRUE; + if (sc->facts->IOCCapabilities & + MPI2_IOCFACTS_CAPABILITY_SNAPSHOT_BUFFER) + sc->fw_diag_buffer_list[MPI2_DIAG_BUF_TYPE_SNAPSHOT]. + enabled = TRUE; + if (sc->facts->IOCCapabilities & + MPI2_IOCFACTS_CAPABILITY_EXTENDED_BUFFER) + sc->fw_diag_buffer_list[MPI2_DIAG_BUF_TYPE_EXTENDED]. + enabled = TRUE; + + /* + * Set flag if EEDP is supported and if TLR is supported. + */ + if (sc->facts->IOCCapabilities & MPI2_IOCFACTS_CAPABILITY_EEDP) + sc->eedp_enabled = TRUE; + if (sc->facts->IOCCapabilities & MPI2_IOCFACTS_CAPABILITY_TLR) + sc->control_TLR = TRUE; + + /* + * Size the queues. Since the reply queues always need one free + * entry, we'll just deduct one reply message here. + */ + sc->num_reqs = MIN(MPS_REQ_FRAMES, sc->facts->RequestCredit); + sc->num_replies = MIN(MPS_REPLY_FRAMES + MPS_EVT_REPLY_FRAMES, + sc->facts->MaxReplyDescriptorPostQueueDepth) - 1; + + /* + * Initialize all Tail Queues + */ + TAILQ_INIT(&sc->req_list); + TAILQ_INIT(&sc->high_priority_req_list); + TAILQ_INIT(&sc->chain_list); + TAILQ_INIT(&sc->tm_list); + } + + /* + * If doing a Diag Reset and the FW is significantly different + * (reallocating will be set above in IOC Facts comparison), then all + * buffers based on the IOC Facts will need to be freed before they are + * reallocated. + */ + if (reallocating) { + mps_iocfacts_free(sc); + + /* + * The number of targets is based on IOC Facts, so free all of + * the allocated LUNs for each target and then the target buffer + * itself. + */ + for (i=0; i< saved_facts.MaxTargets; i++) { + targ = &sc->sassc->targets[i]; + SLIST_FOREACH_SAFE(lun, &targ->luns, lun_link, + lun_tmp) { + free(lun, M_MPT2); + } + } + free(sc->sassc->targets, M_MPT2); + + sc->sassc->targets = malloc(sizeof(struct mpssas_target) * + sc->facts->MaxTargets, M_MPT2, M_WAITOK|M_ZERO); + if (!sc->sassc->targets) { + panic("%s failed to alloc targets with error %d\n", + __func__, ENOMEM); + } + } + + /* + * Any deallocation has been completed. Now start reallocating + * if needed. Will only need to reallocate if attaching or if the new + * IOC Facts are different from the previous IOC Facts after a Diag + * Reset. Targets have already been allocated above if needed. + */ + if (attaching || reallocating) { + if (((error = mps_alloc_queues(sc)) != 0) || + ((error = mps_alloc_replies(sc)) != 0) || + ((error = mps_alloc_requests(sc)) != 0)) { + if (attaching ) { + mps_dprint(sc, MPS_FAULT, "%s failed to alloc " + "queues with error %d\n", __func__, error); + mps_free(sc); + return (error); + } else { + panic("%s failed to alloc queues with error " + "%d\n", __func__, error); + } + } + } + + /* Always initialize the queues */ + bzero(sc->free_queue, sc->fqdepth * 4); + mps_init_queues(sc); + + /* + * Always get the chip out of the reset state, but only panic if not + * attaching. If attaching and there is an error, that is handled by + * the OS. + */ + error = mps_transition_operational(sc); + if (error != 0) { + if (attaching) { + mps_printf(sc, "%s failed to transition to operational " + "with error %d\n", __func__, error); + mps_free(sc); + return (error); + } else { + panic("%s failed to transition to operational with " + "error %d\n", __func__, error); + } + } + + /* + * Finish the queue initialization. + * These are set here instead of in mps_init_queues() because the + * IOC resets these values during the state transition in + * mps_transition_operational(). The free index is set to 1 + * because the corresponding index in the IOC is set to 0, and the + * IOC treats the queues as full if both are set to the same value. + * Hence the reason that the queue can't hold all of the possible + * replies. + */ + sc->replypostindex = 0; + mps_regwrite(sc, MPI2_REPLY_FREE_HOST_INDEX_OFFSET, sc->replyfreeindex); + mps_regwrite(sc, MPI2_REPLY_POST_HOST_INDEX_OFFSET, 0); + + /* + * Attach the subsystems so they can prepare their event masks. + */ + /* XXX Should be dynamic so that IM/IR and user modules can attach */ + if (attaching) { + if (((error = mps_attach_log(sc)) != 0) || + ((error = mps_attach_sas(sc)) != 0) || + ((error = mps_attach_user(sc)) != 0)) { + mps_printf(sc, "%s failed to attach all subsystems: " + "error %d\n", __func__, error); + mps_free(sc); + return (error); + } + + if ((error = mps_pci_setup_interrupts(sc)) != 0) { + mps_printf(sc, "%s failed to setup interrupts\n", + __func__); + mps_free(sc); + return (error); + } + } + + /* + * Set flag if this is a WD controller. This shouldn't ever change, but + * reset it after a Diag Reset, just in case. + */ + sc->WD_available = FALSE; + if (pci_get_device(sc->mps_dev) == MPI2_MFGPAGE_DEVID_SSS6200) + sc->WD_available = TRUE; + + return (error); + } + + /* + * This is called if memory is being free (during detach for example) and when + * buffers need to be reallocated due to a Diag Reset. + */ + static void + mps_iocfacts_free(struct mps_softc *sc) + { + struct mps_command *cm; + int i; + + mps_dprint(sc, MPS_TRACE, "%s\n", __func__); + + if (sc->post_busaddr != 0) + bus_dmamap_unload(sc->queues_dmat, sc->queues_map); + if (sc->post_queue != NULL) + bus_dmamem_free(sc->queues_dmat, sc->post_queue, + sc->queues_map); + if (sc->queues_dmat != NULL) + bus_dma_tag_destroy(sc->queues_dmat); + + if (sc->chain_busaddr != 0) + bus_dmamap_unload(sc->chain_dmat, sc->chain_map); + if (sc->chain_frames != NULL) + bus_dmamem_free(sc->chain_dmat, sc->chain_frames, + sc->chain_map); + if (sc->chain_dmat != NULL) + bus_dma_tag_destroy(sc->chain_dmat); + + if (sc->sense_busaddr != 0) + bus_dmamap_unload(sc->sense_dmat, sc->sense_map); + if (sc->sense_frames != NULL) + bus_dmamem_free(sc->sense_dmat, sc->sense_frames, + sc->sense_map); + if (sc->sense_dmat != NULL) + bus_dma_tag_destroy(sc->sense_dmat); + + if (sc->reply_busaddr != 0) + bus_dmamap_unload(sc->reply_dmat, sc->reply_map); + if (sc->reply_frames != NULL) + bus_dmamem_free(sc->reply_dmat, sc->reply_frames, + sc->reply_map); + if (sc->reply_dmat != NULL) + bus_dma_tag_destroy(sc->reply_dmat); + + if (sc->req_busaddr != 0) + bus_dmamap_unload(sc->req_dmat, sc->req_map); + if (sc->req_frames != NULL) + bus_dmamem_free(sc->req_dmat, sc->req_frames, sc->req_map); + if (sc->req_dmat != NULL) + bus_dma_tag_destroy(sc->req_dmat); + + if (sc->chains != NULL) + free(sc->chains, M_MPT2); + if (sc->commands != NULL) { + for (i = 1; i < sc->num_reqs; i++) { + cm = &sc->commands[i]; + bus_dmamap_destroy(sc->buffer_dmat, cm->cm_dmamap); + } + free(sc->commands, M_MPT2); + } + if (sc->buffer_dmat != NULL) + bus_dma_tag_destroy(sc->buffer_dmat); + } + /* * The terms diag reset and hard reset are used interchangeably in the MPI * docs to mean resetting the controller chip. In this code diag reset * cleans everything up, and the hard reset function just sends the reset *************** *** 316,322 **** mps_reinit(struct mps_softc *sc) { int error; - uint32_t db; mps_printf(sc, "%s sc %p\n", __func__, sc); --- 675,680 ---- *************** *** 332,344 **** */ sc->mps_flags |= MPS_FLAGS_DIAGRESET; mps_printf(sc, "%s mask interrupts\n", __func__); mps_mask_intr(sc); error = mps_diag_reset(sc, CAN_SLEEP); if (error != 0) { ! panic("%s hard reset failed with error %d\n", ! __func__, error); } /* Restore the PCI state, including the MSI-X registers */ --- 690,704 ---- */ sc->mps_flags |= MPS_FLAGS_DIAGRESET; + /* + * Mask interrupts here. + */ mps_printf(sc, "%s mask interrupts\n", __func__); mps_mask_intr(sc); error = mps_diag_reset(sc, CAN_SLEEP); if (error != 0) { ! panic("%s hard reset failed with error %d\n", __func__, error); } /* Restore the PCI state, including the MSI-X registers */ *************** *** 347,395 **** /* Give the I/O subsystem special priority to get itself prepared */ mpssas_handle_reinit(sc); ! /* reinitialize queues after the reset */ ! bzero(sc->free_queue, sc->fqdepth * 4); ! mps_init_queues(sc); ! ! /* get the chip out of the reset state */ ! error = mps_transition_operational(sc); ! if (error != 0) ! panic("%s transition operational failed with error %d\n", __func__, error); ! /* Reinitialize the reply queue. This is delicate because this ! * function is typically invoked by task mgmt completion callbacks, ! * which are called by the interrupt thread. We need to make sure ! * the interrupt handler loop will exit when we return to it, and ! * that it will recognize the indexes we've changed. */ ! sc->replypostindex = 0; ! mps_regwrite(sc, MPI2_REPLY_FREE_HOST_INDEX_OFFSET, sc->replyfreeindex); ! mps_regwrite(sc, MPI2_REPLY_POST_HOST_INDEX_OFFSET, sc->replypostindex); ! db = mps_regread(sc, MPI2_DOORBELL_OFFSET); ! mps_printf(sc, "%s doorbell 0x%08x\n", __func__, db); ! ! mps_printf(sc, "%s unmask interrupts post %u free %u\n", __func__, ! sc->replypostindex, sc->replyfreeindex); ! mps_unmask_intr(sc); ! mps_printf(sc, "%s restarting post %u free %u\n", __func__, ! sc->replypostindex, sc->replyfreeindex); ! /* restart will reload the event masks clobbered by the reset, and * then enable the port. */ mps_reregister_events(sc); /* the end of discovery will release the simq, so we're done. */ ! mps_printf(sc, "%s finished sc %p post %u free %u\n", ! __func__, sc, sc->replypostindex, sc->replyfreeindex); - sc->mps_flags &= ~MPS_FLAGS_DIAGRESET; - return 0; } --- 707,756 ---- /* Give the I/O subsystem special priority to get itself prepared */ mpssas_handle_reinit(sc); ! /* ! * Get IOC Facts and allocate all structures based on this information. ! * The attach function will also call mps_iocfacts_allocate at startup. ! * If relevant values have changed in IOC Facts, this function will free ! * all of the memory based on IOC Facts and reallocate that memory. ! */ ! if ((error = mps_iocfacts_allocate(sc, FALSE)) != 0) { ! panic("%s IOC Facts based allocation failed with error %d\n", __func__, error); + } ! /* ! * Mapping structures will be re-allocated after getting IOC Page8, so ! * free these structures here. */ ! mps_mapping_exit(sc); ! /* ! * The static page function currently read is IOC Page8. Others can be ! * added in future. It's possible that the values in IOC Page8 have ! * changed after a Diag Reset due to user modification, so always read ! * these. Interrupts are masked, so unmask them before getting config ! * pages. ! */ mps_unmask_intr(sc); + sc->mps_flags &= ~MPS_FLAGS_DIAGRESET; + mps_base_static_config_pages(sc); ! /* ! * Some mapping info is based in IOC Page8 data, so re-initialize the ! * mapping tables. ! */ ! mps_mapping_initialize(sc); ! /* ! * Restart will reload the event masks clobbered by the reset, and * then enable the port. */ mps_reregister_events(sc); /* the end of discovery will release the simq, so we're done. */ ! mps_printf(sc, "%s finished sc %p post %u free %u\n", __func__, sc, sc->replypostindex, sc->replyfreeindex); return 0; } *************** *** 634,681 **** } static int - mps_get_portfacts(struct mps_softc *sc, MPI2_PORT_FACTS_REPLY *facts, int port) - { - MPI2_PORT_FACTS_REQUEST *request; - MPI2_PORT_FACTS_REPLY *reply; - struct mps_command *cm; - int error; - - mps_dprint(sc, MPS_TRACE, "%s\n", __func__); - - if ((cm = mps_alloc_command(sc)) == NULL) - return (EBUSY); - request = (MPI2_PORT_FACTS_REQUEST *)cm->cm_req; - request->Function = MPI2_FUNCTION_PORT_FACTS; - request->PortNumber = port; - cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; - cm->cm_data = NULL; - error = mps_request_polled(sc, cm); - reply = (MPI2_PORT_FACTS_REPLY *)cm->cm_reply; - if (reply == NULL) { - mps_printf(sc, "%s NULL reply\n", __func__); - goto done; - } - if ((reply->IOCStatus & MPI2_IOCSTATUS_MASK) != MPI2_IOCSTATUS_SUCCESS) { - mps_printf(sc, - "%s error %d iocstatus 0x%x iocloginfo 0x%x type 0x%x\n", - __func__, error, reply->IOCStatus, reply->IOCLogInfo, - reply->PortType); - error = ENXIO; - } - bcopy(reply, facts, sizeof(MPI2_PORT_FACTS_REPLY)); - done: - mps_free_command(sc, cm); - - return (error); - } - - static int mps_send_iocinit(struct mps_softc *sc) { MPI2_IOC_INIT_REQUEST init; MPI2_DEFAULT_REPLY reply; int req_sz, reply_sz, error; mps_dprint(sc, MPS_TRACE, "%s\n", __func__); --- 995,1007 ---- } static int mps_send_iocinit(struct mps_softc *sc) { MPI2_IOC_INIT_REQUEST init; MPI2_DEFAULT_REPLY reply; int req_sz, reply_sz, error; + struct timeval now; + uint64_t time_in_msec; mps_dprint(sc, MPS_TRACE, "%s\n", __func__); *************** *** 704,711 **** init.ReplyDescriptorPostQueueAddress.Low = htole32((uint32_t)sc->post_busaddr); init.ReplyFreeQueueAddress.High = 0; init.ReplyFreeQueueAddress.Low = htole32((uint32_t)sc->free_busaddr); ! init.TimeStamp.High = 0; ! init.TimeStamp.Low = htole32((uint32_t)time_uptime); error = mps_request_sync(sc, &init, &reply, req_sz, reply_sz, 5); if ((reply.IOCStatus & MPI2_IOCSTATUS_MASK) != MPI2_IOCSTATUS_SUCCESS) --- 1030,1039 ---- init.ReplyDescriptorPostQueueAddress.Low = htole32((uint32_t)sc->post_busaddr); init.ReplyFreeQueueAddress.High = 0; init.ReplyFreeQueueAddress.Low = htole32((uint32_t)sc->free_busaddr); ! getmicrotime(&now); ! time_in_msec = (now.tv_sec * 1000 + now.tv_usec/1000); ! init.TimeStamp.High = htole32((time_in_msec >> 32) & 0xFFFFFFFF); ! init.TimeStamp.Low = htole32(time_in_msec & 0xFFFFFFFF); error = mps_request_sync(sc, &init, &reply, req_sz, reply_sz, 5); if ((reply.IOCStatus & MPI2_IOCSTATUS_MASK) != MPI2_IOCSTATUS_SUCCESS) *************** *** 1119,1125 **** int mps_attach(struct mps_softc *sc) { ! int i, error; mps_get_tunables(sc); --- 1447,1453 ---- int mps_attach(struct mps_softc *sc) { ! int error; mps_get_tunables(sc); *************** *** 1141,1291 **** __func__, __LINE__); return (ENOMEM); } - if ((error = mps_get_iocfacts(sc, sc->facts)) != 0) - return (error); - - mps_print_iocfacts(sc, sc->facts); - - snprintf(sc->fw_version, sizeof(sc->fw_version), - "%02d.%02d.%02d.%02d", - sc->facts->FWVersion.Struct.Major, - sc->facts->FWVersion.Struct.Minor, - sc->facts->FWVersion.Struct.Unit, - sc->facts->FWVersion.Struct.Dev); - mps_printf(sc, "Firmware: %s, Driver: %s\n", sc->fw_version, - MPS_DRIVER_VERSION); - mps_printf(sc, "IOCCapabilities: %b\n", sc->facts->IOCCapabilities, - "\20" "\3ScsiTaskFull" "\4DiagTrace" "\5SnapBuf" "\6ExtBuf" - "\7EEDP" "\10BiDirTarg" "\11Multicast" "\14TransRetry" "\15IR" - "\16EventReplay" "\17RaidAccel" "\20MSIXIndex" "\21HostDisc"); - /* ! * If the chip doesn't support event replay then a hard reset will be ! * required to trigger a full discovery. Do the reset here then ! * retransition to Ready. A hard reset might have already been done, ! * but it doesn't hurt to do it again. */ ! if ((sc->facts->IOCCapabilities & ! MPI2_IOCFACTS_CAPABILITY_EVENT_REPLAY) == 0) { ! mps_diag_reset(sc, NO_SLEEP); ! if ((error = mps_transition_ready(sc)) != 0) ! return (error); ! } ! ! /* ! * Set flag if IR Firmware is loaded. ! */ ! if (sc->facts->IOCCapabilities & ! MPI2_IOCFACTS_CAPABILITY_INTEGRATED_RAID) ! sc->ir_firmware = 1; ! ! /* ! * Check if controller supports FW diag buffers and set flag to enable ! * each type. ! */ ! if (sc->facts->IOCCapabilities & ! MPI2_IOCFACTS_CAPABILITY_DIAG_TRACE_BUFFER) ! sc->fw_diag_buffer_list[MPI2_DIAG_BUF_TYPE_TRACE].enabled = ! TRUE; ! if (sc->facts->IOCCapabilities & ! MPI2_IOCFACTS_CAPABILITY_SNAPSHOT_BUFFER) ! sc->fw_diag_buffer_list[MPI2_DIAG_BUF_TYPE_SNAPSHOT].enabled = ! TRUE; ! if (sc->facts->IOCCapabilities & ! MPI2_IOCFACTS_CAPABILITY_EXTENDED_BUFFER) ! sc->fw_diag_buffer_list[MPI2_DIAG_BUF_TYPE_EXTENDED].enabled = ! TRUE; ! ! /* ! * Set flag if EEDP is supported and if TLR is supported. ! */ ! if (sc->facts->IOCCapabilities & MPI2_IOCFACTS_CAPABILITY_EEDP) ! sc->eedp_enabled = TRUE; ! if (sc->facts->IOCCapabilities & MPI2_IOCFACTS_CAPABILITY_TLR) ! sc->control_TLR = TRUE; ! ! /* ! * Size the queues. Since the reply queues always need one free entry, ! * we'll just deduct one reply message here. ! */ ! sc->num_reqs = MIN(MPS_REQ_FRAMES, sc->facts->RequestCredit); ! sc->num_replies = MIN(MPS_REPLY_FRAMES + MPS_EVT_REPLY_FRAMES, ! sc->facts->MaxReplyDescriptorPostQueueDepth) - 1; ! TAILQ_INIT(&sc->req_list); ! TAILQ_INIT(&sc->high_priority_req_list); ! TAILQ_INIT(&sc->chain_list); ! TAILQ_INIT(&sc->tm_list); ! ! if (((error = mps_alloc_queues(sc)) != 0) || ! ((error = mps_alloc_replies(sc)) != 0) || ! ((error = mps_alloc_requests(sc)) != 0)) { ! mps_printf(sc, "%s failed to alloc\n", __func__); ! mps_free(sc); ! return (error); ! } ! ! if (((error = mps_init_queues(sc)) != 0) || ! ((error = mps_transition_operational(sc)) != 0)) { ! mps_printf(sc, "%s failed to transition operational\n", __func__); ! mps_free(sc); ! return (error); ! } ! ! /* ! * Finish the queue initialization. ! * These are set here instead of in mps_init_queues() because the ! * IOC resets these values during the state transition in ! * mps_transition_operational(). The free index is set to 1 ! * because the corresponding index in the IOC is set to 0, and the ! * IOC treats the queues as full if both are set to the same value. ! * Hence the reason that the queue can't hold all of the possible ! * replies. ! */ ! sc->replypostindex = 0; ! mps_regwrite(sc, MPI2_REPLY_FREE_HOST_INDEX_OFFSET, sc->replyfreeindex); ! mps_regwrite(sc, MPI2_REPLY_POST_HOST_INDEX_OFFSET, 0); ! ! sc->pfacts = malloc(sizeof(MPI2_PORT_FACTS_REPLY) * ! sc->facts->NumberOfPorts, M_MPT2, M_ZERO|M_WAITOK); ! if(!sc->pfacts) { ! device_printf(sc->mps_dev, "Cannot allocate memory %s %d\n", ! __func__, __LINE__); ! return (ENOMEM); ! } ! for (i = 0; i < sc->facts->NumberOfPorts; i++) { ! if ((error = mps_get_portfacts(sc, &sc->pfacts[i], i)) != 0) { ! mps_printf(sc, "%s failed to get portfacts for port %d\n", ! __func__, i); ! mps_free(sc); ! return (error); ! } ! mps_print_portfacts(sc, &sc->pfacts[i]); ! } ! ! /* Attach the subsystems so they can prepare their event masks. */ ! /* XXX Should be dynamic so that IM/IR and user modules can attach */ ! if (((error = mps_attach_log(sc)) != 0) || ! ((error = mps_attach_sas(sc)) != 0) || ! ((error = mps_attach_user(sc)) != 0)) { ! mps_printf(sc, "%s failed to attach all subsystems: error %d\n", ! __func__, error); ! mps_free(sc); ! return (error); ! } ! ! if ((error = mps_pci_setup_interrupts(sc)) != 0) { ! mps_printf(sc, "%s failed to setup interrupts\n", __func__); ! mps_free(sc); return (error); } - /* - * The static page function currently read is ioc page8. Others can be - * added in future. - */ - mps_base_static_config_pages(sc); - /* Start the periodic watchdog check on the IOC Doorbell */ mps_periodic(sc); --- 1469,1488 ---- __func__, __LINE__); return (ENOMEM); } /* ! * Get IOC Facts and allocate all structures based on this information. ! * A Diag Reset will also call mps_iocfacts_allocate and re-read the IOC ! * Facts. If relevant values have changed in IOC Facts, this function ! * will free all of the memory based on IOC Facts and reallocate that ! * memory. If this fails, any allocated memory should already be freed. */ ! if ((error = mps_iocfacts_allocate(sc, TRUE)) != 0) { ! mps_dprint(sc, MPS_FAULT, "%s IOC Facts based allocation " ! "failed with error %d\n", __func__, error); return (error); } /* Start the periodic watchdog check on the IOC Doorbell */ mps_periodic(sc); *************** *** 1328,1334 **** --- 1525,1533 ---- mps_lock(sc); mps_unmask_intr(sc); + /* initialize device mapping tables */ + mps_base_static_config_pages(sc); mps_mapping_initialize(sc); mpssas_startup(sc); mps_unlock(sc); *************** *** 1411,1418 **** int mps_free(struct mps_softc *sc) { ! struct mps_command *cm; ! int i, error; /* Turn off the watchdog */ mps_lock(sc); --- 1610,1616 ---- int mps_free(struct mps_softc *sc) { ! int error; /* Turn off the watchdog */ mps_lock(sc); *************** *** 1438,1499 **** if (sc->facts != NULL) free(sc->facts, M_MPT2); ! if (sc->pfacts != NULL) ! free(sc->pfacts, M_MPT2); ! ! if (sc->post_busaddr != 0) ! bus_dmamap_unload(sc->queues_dmat, sc->queues_map); ! if (sc->post_queue != NULL) ! bus_dmamem_free(sc->queues_dmat, sc->post_queue, ! sc->queues_map); ! if (sc->queues_dmat != NULL) ! bus_dma_tag_destroy(sc->queues_dmat); ! ! if (sc->chain_busaddr != 0) ! bus_dmamap_unload(sc->chain_dmat, sc->chain_map); ! if (sc->chain_frames != NULL) ! bus_dmamem_free(sc->chain_dmat, sc->chain_frames,sc->chain_map); ! if (sc->chain_dmat != NULL) ! bus_dma_tag_destroy(sc->chain_dmat); ! ! if (sc->sense_busaddr != 0) ! bus_dmamap_unload(sc->sense_dmat, sc->sense_map); ! if (sc->sense_frames != NULL) ! bus_dmamem_free(sc->sense_dmat, sc->sense_frames,sc->sense_map); ! if (sc->sense_dmat != NULL) ! bus_dma_tag_destroy(sc->sense_dmat); ! ! if (sc->reply_busaddr != 0) ! bus_dmamap_unload(sc->reply_dmat, sc->reply_map); ! if (sc->reply_frames != NULL) ! bus_dmamem_free(sc->reply_dmat, sc->reply_frames,sc->reply_map); ! if (sc->reply_dmat != NULL) ! bus_dma_tag_destroy(sc->reply_dmat); ! ! if (sc->req_busaddr != 0) ! bus_dmamap_unload(sc->req_dmat, sc->req_map); ! if (sc->req_frames != NULL) ! bus_dmamem_free(sc->req_dmat, sc->req_frames, sc->req_map); ! if (sc->req_dmat != NULL) ! bus_dma_tag_destroy(sc->req_dmat); - if (sc->chains != NULL) - free(sc->chains, M_MPT2); - if (sc->commands != NULL) { - for (i = 1; i < sc->num_reqs; i++) { - cm = &sc->commands[i]; - bus_dmamap_destroy(sc->buffer_dmat, cm->cm_dmamap); - } - free(sc->commands, M_MPT2); - } - if (sc->buffer_dmat != NULL) - bus_dma_tag_destroy(sc->buffer_dmat); - if (sc->sysctl_tree != NULL) sysctl_ctx_free(&sc->sysctl_ctx); - mps_mapping_free_memory(sc); - /* Deregister the shutdown function */ if (sc->shutdown_eh != NULL) EVENTHANDLER_DEREGISTER(shutdown_final, sc->shutdown_eh); --- 1636,1650 ---- if (sc->facts != NULL) free(sc->facts, M_MPT2); ! /* ! * Free all buffers that are based on IOC Facts. A Diag Reset may need ! * to free these buffers too. ! */ ! mps_iocfacts_free(sc); if (sc->sysctl_tree != NULL) sysctl_ctx_free(&sc->sysctl_ctx); /* Deregister the shutdown function */ if (sc->shutdown_eh != NULL) EVENTHANDLER_DEREGISTER(shutdown_final, sc->shutdown_eh); *************** *** 1914,1920 **** /* first, reregister events */ ! for (i = 0; i < MPI2_EVENT_NOTIFY_EVENTMASK_WORDS; i++) sc->event_mask[i] = -1; TAILQ_FOREACH(eh, &sc->event_list, eh_list) { --- 2065,2071 ---- /* first, reregister events */ ! for (i = 0; i < MPI2_EVENT_NOTIFY_EVENTMASK_WORDS; i++) sc->event_mask[i] = -1; TAILQ_FOREACH(eh, &sc->event_list, eh_list) { *************** *** 1946,1952 **** error = mps_map_command(sc, cm); ! mps_dprint(sc, MPS_TRACE, "%s finished with error %d\n", __func__, error); return (error); } --- 2097,2104 ---- error = mps_map_command(sc, cm); ! mps_dprint(sc, MPS_TRACE, "%s finished with error %d\n", __func__, ! error); return (error); } *************** *** 2325,2350 **** * be executed and enqueued automatically. Other errors come from msleep(). */ int ! mps_wait_command(struct mps_softc *sc, struct mps_command *cm, int timeout) { int error, rc; ! mtx_assert(&sc->mps_mtx, MA_OWNED); ! ! if(sc->mps_flags & MPS_FLAGS_DIAGRESET) return EBUSY; cm->cm_complete = NULL; ! cm->cm_flags |= MPS_CM_FLAGS_WAKEUP; error = mps_map_command(sc, cm); if ((error != 0) && (error != EINPROGRESS)) return (error); ! error = msleep(cm, &sc->mps_mtx, 0, "mpswait", timeout*hz); if (error == EWOULDBLOCK) { mps_dprint(sc, MPS_FAULT, "Calling Reinit from %s\n", __func__); rc = mps_reinit(sc); ! mps_dprint(sc, MPS_FAULT, "Reinit %s\n", ! (rc == 0) ? "success" : "failed"); error = ETIMEDOUT; } return (error); --- 2477,2526 ---- * be executed and enqueued automatically. Other errors come from msleep(). */ int ! mps_wait_command(struct mps_softc *sc, struct mps_command *cm, int timeout, ! int sleep_flag) { int error, rc; + struct timeval cur_time, start_time; ! if (sc->mps_flags & MPS_FLAGS_DIAGRESET) return EBUSY; cm->cm_complete = NULL; ! cm->cm_flags |= (MPS_CM_FLAGS_WAKEUP + MPS_CM_FLAGS_POLLED); error = mps_map_command(sc, cm); if ((error != 0) && (error != EINPROGRESS)) return (error); ! ! // Check for context and wait for 50 mSec at a time until time has ! // expired or the command has finished. If msleep can't be used, need ! // to poll. ! if (curthread->td_pflags & TDP_NOSLEEPING) ! sleep_flag = NO_SLEEP; ! getmicrotime(&start_time); ! if (mtx_owned(&sc->mps_mtx) && sleep_flag == CAN_SLEEP) { ! error = msleep(cm, &sc->mps_mtx, 0, "mpswait", timeout*hz); ! } else { ! while ((cm->cm_flags & MPS_CM_FLAGS_COMPLETE) == 0) { ! mps_intr_locked(sc); ! if (sleep_flag == CAN_SLEEP) ! pause("mpswait", hz/20); ! else ! DELAY(50000); ! ! getmicrotime(&cur_time); ! if ((cur_time.tv_sec - start_time.tv_sec) > timeout) { ! error = EWOULDBLOCK; ! break; ! } ! } ! } ! if (error == EWOULDBLOCK) { mps_dprint(sc, MPS_FAULT, "Calling Reinit from %s\n", __func__); rc = mps_reinit(sc); ! mps_dprint(sc, MPS_FAULT, "Reinit %s\n", (rc == 0) ? "success" : ! "failed"); error = ETIMEDOUT; } return (error); *************** *** 2444,2450 **** cm->cm_complete = mps_config_complete; return (mps_map_command(sc, cm)); } else { ! error = mps_wait_command(sc, cm, 0); if (error) { mps_dprint(sc, MPS_FAULT, "Error %d reading config page\n", error); --- 2620,2626 ---- cm->cm_complete = mps_config_complete; return (mps_map_command(sc, cm)); } else { ! error = mps_wait_command(sc, cm, 0, CAN_SLEEP); if (error) { mps_dprint(sc, MPS_FAULT, "Error %d reading config page\n", error); *** src/sys/dev/mps/mps_config.c.orig --- src/sys/dev/mps/mps_config.c *************** *** 93,104 **** request->Header.PageVersion = MPI2_IOCPAGE8_PAGEVERSION; cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; cm->cm_data = NULL; ! error = mps_request_polled(sc, cm); reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; if (error || (reply == NULL)) { /* FIXME */ ! /* If the poll returns error then we need to do diag reset */ ! printf("%s: poll for header completed with error %d", __func__, error); error = ENXIO; goto out; --- 93,107 ---- request->Header.PageVersion = MPI2_IOCPAGE8_PAGEVERSION; cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; cm->cm_data = NULL; ! error = mps_wait_command(sc, cm, 60, CAN_SLEEP); reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; if (error || (reply == NULL)) { /* FIXME */ ! /* ! * If the request returns an error then we need to do a diag ! * reset ! */ ! printf("%s: request for header completed with error %d", __func__, error); error = ENXIO; goto out; *************** *** 107,113 **** bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { /* FIXME */ ! /* If the poll returns error then we need to do diag reset */ printf("%s: header read with error; iocstatus = 0x%x\n", __func__, ioc_status); error = ENXIO; --- 110,119 ---- bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { /* FIXME */ ! /* ! * If the request returns an error then we need to do a diag ! * reset ! */ printf("%s: header read with error; iocstatus = 0x%x\n", __func__, ioc_status); error = ENXIO; *************** *** 144,155 **** goto out; } cm->cm_data = page; ! error = mps_request_polled(sc, cm); reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; if (error || (reply == NULL)) { /* FIXME */ ! /* If the poll returns error then we need to do diag reset */ ! printf("%s: poll for page completed with error %d", __func__, error); error = ENXIO; goto out; --- 150,165 ---- goto out; } cm->cm_data = page; ! ! error = mps_wait_command(sc, cm, 60, CAN_SLEEP); reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; if (error || (reply == NULL)) { /* FIXME */ ! /* ! * If the request returns an error then we need to do a diag ! * reset ! */ ! printf("%s: request for page completed with error %d", __func__, error); error = ENXIO; goto out; *************** *** 158,164 **** bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { /* FIXME */ ! /* If the poll returns error then we need to do diag reset */ printf("%s: page read with error; iocstatus = 0x%x\n", __func__, ioc_status); error = ENXIO; --- 168,177 ---- bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { /* FIXME */ ! /* ! * If the request returns an error then we need to do a diag ! * reset ! */ printf("%s: page read with error; iocstatus = 0x%x\n", __func__, ioc_status); error = ENXIO; *************** *** 211,216 **** --- 224,234 ---- request->Header.PageVersion = MPI2_MANUFACTURING10_PAGEVERSION; cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; cm->cm_data = NULL; + + /* + * This page must be polled because the IOC isn't ready yet when this + * page is needed. + */ error = mps_request_polled(sc, cm); reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; if (error || (reply == NULL)) { *************** *** 262,267 **** --- 280,290 ---- goto out; } cm->cm_data = page; + + /* + * This page must be polled because the IOC isn't ready yet when this + * page is needed. + */ error = mps_request_polled(sc, cm); reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; if (error || (reply == NULL)) { *************** *** 561,572 **** MPI2_DPM_PGAD_ENTRY_COUNT_SHIFT; cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; cm->cm_data = NULL; ! error = mps_request_polled(sc, cm); reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; if (error || (reply == NULL)) { /* FIXME */ ! /* If the poll returns error then we need to do diag reset */ ! printf("%s: poll for header completed with error %d", __func__, error); error = ENXIO; goto out; --- 584,598 ---- MPI2_DPM_PGAD_ENTRY_COUNT_SHIFT; cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; cm->cm_data = NULL; ! error = mps_wait_command(sc, cm, 60, CAN_SLEEP); reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; if (error || (reply == NULL)) { /* FIXME */ ! /* ! * If the request returns an error then we need to do a diag ! * reset ! */ ! printf("%s: request for header completed with error %d", __func__, error); error = ENXIO; goto out; *************** *** 575,581 **** bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { /* FIXME */ ! /* If the poll returns error then we need to do diag reset */ printf("%s: header read with error; iocstatus = 0x%x\n", __func__, ioc_status); error = ENXIO; --- 601,610 ---- bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { /* FIXME */ ! /* ! * If the request returns an error then we need to do a diag ! * reset ! */ printf("%s: header read with error; iocstatus = 0x%x\n", __func__, ioc_status); error = ENXIO; *************** *** 615,626 **** goto out; } cm->cm_data = page; ! error = mps_request_polled(sc, cm); reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; if (error || (reply == NULL)) { /* FIXME */ ! /* If the poll returns error then we need to do diag reset */ ! printf("%s: poll for page completed with error %d", __func__, error); error = ENXIO; goto out; --- 644,658 ---- goto out; } cm->cm_data = page; ! error = mps_wait_command(sc, cm, 60, CAN_SLEEP); reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; if (error || (reply == NULL)) { /* FIXME */ ! /* ! * If the request returns an error then we need to do a diag ! * reset ! */ ! printf("%s: request for page completed with error %d", __func__, error); error = ENXIO; goto out; *************** *** 629,635 **** bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { /* FIXME */ ! /* If the poll returns error then we need to do diag reset */ printf("%s: page read with error; iocstatus = 0x%x\n", __func__, ioc_status); error = ENXIO; --- 661,670 ---- bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { /* FIXME */ ! /* ! * If the request returns an error then we need to do a diag ! * reset ! */ printf("%s: page read with error; iocstatus = 0x%x\n", __func__, ioc_status); error = ENXIO; *************** *** 685,696 **** request->PageAddress |= htole16(entry_idx); cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; cm->cm_data = NULL; ! error = mps_request_polled(sc, cm); reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; if (error || (reply == NULL)) { /* FIXME */ ! /* If the poll returns error then we need to do diag reset */ ! printf("%s: poll for header completed with error %d", __func__, error); error = ENXIO; goto out; --- 720,734 ---- request->PageAddress |= htole16(entry_idx); cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; cm->cm_data = NULL; ! error = mps_wait_command(sc, cm, 60, CAN_SLEEP); reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; if (error || (reply == NULL)) { /* FIXME */ ! /* ! * If the request returns an error then we need to do a diag ! * reset ! */ ! printf("%s: request for header completed with error %d", __func__, error); error = ENXIO; goto out; *************** *** 699,705 **** bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { /* FIXME */ ! /* If the poll returns error then we need to do diag reset */ printf("%s: header read with error; iocstatus = 0x%x\n", __func__, ioc_status); error = ENXIO; --- 737,746 ---- bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { /* FIXME */ ! /* ! * If the request returns an error then we need to do a diag ! * reset ! */ printf("%s: header read with error; iocstatus = 0x%x\n", __func__, ioc_status); error = ENXIO; *************** *** 741,752 **** bcopy(config_page, page, MIN(cm->cm_length, (sizeof(Mpi2DriverMappingPage0_t)))); cm->cm_data = page; ! error = mps_request_polled(sc, cm); reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; if (error || (reply == NULL)) { /* FIXME */ ! /* If the poll returns error then we need to do diag reset */ ! printf("%s: poll for page completed with error %d", __func__, error); error = ENXIO; goto out; --- 782,796 ---- bcopy(config_page, page, MIN(cm->cm_length, (sizeof(Mpi2DriverMappingPage0_t)))); cm->cm_data = page; ! error = mps_wait_command(sc, cm, 60, CAN_SLEEP); reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; if (error || (reply == NULL)) { /* FIXME */ ! /* ! * If the request returns an error then we need to do a diag ! * reset ! */ ! printf("%s: request to write page completed with error %d", __func__, error); error = ENXIO; goto out; *************** *** 755,761 **** bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { /* FIXME */ ! /* If the poll returns error then we need to do diag reset */ printf("%s: page written with error; iocstatus = 0x%x\n", __func__, ioc_status); error = ENXIO; --- 799,808 ---- bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { /* FIXME */ ! /* ! * If the request returns an error then we need to do a diag ! * reset ! */ printf("%s: page written with error; iocstatus = 0x%x\n", __func__, ioc_status); error = ENXIO; *************** *** 808,819 **** request->Header.PageVersion = MPI2_SASDEVICE0_PAGEVERSION; cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; cm->cm_data = NULL; ! error = mps_request_polled(sc, cm); reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; if (error || (reply == NULL)) { /* FIXME */ ! /* If the poll returns error then we need to do diag reset */ ! printf("%s: poll for header completed with error %d", __func__, error); error = ENXIO; goto out; --- 855,869 ---- request->Header.PageVersion = MPI2_SASDEVICE0_PAGEVERSION; cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; cm->cm_data = NULL; ! error = mps_wait_command(sc, cm, 60, CAN_SLEEP); reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; if (error || (reply == NULL)) { /* FIXME */ ! /* ! * If the request returns an error then we need to do a diag ! * reset ! */ ! printf("%s: request for header completed with error %d", __func__, error); error = ENXIO; goto out; *************** *** 822,828 **** bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { /* FIXME */ ! /* If the poll returns error then we need to do diag reset */ printf("%s: header read with error; iocstatus = 0x%x\n", __func__, ioc_status); error = ENXIO; --- 872,881 ---- bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { /* FIXME */ ! /* ! * If the request returns an error then we need to do a diag ! * reset ! */ printf("%s: header read with error; iocstatus = 0x%x\n", __func__, ioc_status); error = ENXIO; *************** *** 862,873 **** } cm->cm_data = page; ! error = mps_request_polled(sc, cm); reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; if (error || (reply == NULL)) { /* FIXME */ ! /* If the poll returns error then we need to do diag reset */ ! printf("%s: poll for page completed with error %d", __func__, error); error = ENXIO; goto out; --- 915,929 ---- } cm->cm_data = page; ! error = mps_wait_command(sc, cm, 60, CAN_SLEEP); reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; if (error || (reply == NULL)) { /* FIXME */ ! /* ! * If the request returns an error then we need to do a diag ! * reset ! */ ! printf("%s: request for page completed with error %d", __func__, error); error = ENXIO; goto out; *************** *** 876,882 **** bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { /* FIXME */ ! /* If the poll returns error then we need to do diag reset */ printf("%s: page read with error; iocstatus = 0x%x\n", __func__, ioc_status); error = ENXIO; --- 932,941 ---- bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { /* FIXME */ ! /* ! * If the request returns an error then we need to do a diag ! * reset ! */ printf("%s: page read with error; iocstatus = 0x%x\n", __func__, ioc_status); error = ENXIO; *************** *** 928,939 **** request->Header.PageVersion = MPI2_BIOSPAGE3_PAGEVERSION; cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; cm->cm_data = NULL; ! error = mps_request_polled(sc, cm); reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; if (error || (reply == NULL)) { /* FIXME */ ! /* If the poll returns error then we need to do diag reset */ ! printf("%s: poll for header completed with error %d", __func__, error); error = ENXIO; goto out; --- 987,1001 ---- request->Header.PageVersion = MPI2_BIOSPAGE3_PAGEVERSION; cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; cm->cm_data = NULL; ! error = mps_wait_command(sc, cm, 60, CAN_SLEEP); reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; if (error || (reply == NULL)) { /* FIXME */ ! /* ! * If the request returns an error then we need to do a diag ! * reset ! */ ! printf("%s: request for header completed with error %d", __func__, error); error = ENXIO; goto out; *************** *** 942,948 **** bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { /* FIXME */ ! /* If the poll returns error then we need to do diag reset */ printf("%s: header read with error; iocstatus = 0x%x\n", __func__, ioc_status); error = ENXIO; --- 1004,1013 ---- bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { /* FIXME */ ! /* ! * If the request returns an error then we need to do a diag ! * reset ! */ printf("%s: header read with error; iocstatus = 0x%x\n", __func__, ioc_status); error = ENXIO; *************** *** 980,991 **** } cm->cm_data = page; ! error = mps_request_polled(sc, cm); reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; if (error || (reply == NULL)) { /* FIXME */ ! /* If the poll returns error then we need to do diag reset */ ! printf("%s: poll for page completed with error %d", __func__, error); error = ENXIO; goto out; --- 1045,1059 ---- } cm->cm_data = page; ! error = mps_wait_command(sc, cm, 60, CAN_SLEEP); reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; if (error || (reply == NULL)) { /* FIXME */ ! /* ! * If the request returns an error then we need to do a diag ! * reset ! */ ! printf("%s: request for page completed with error %d", __func__, error); error = ENXIO; goto out; *************** *** 994,1000 **** bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { /* FIXME */ ! /* If the poll returns error then we need to do diag reset */ printf("%s: page read with error; iocstatus = 0x%x\n", __func__, ioc_status); error = ENXIO; --- 1062,1071 ---- bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { /* FIXME */ ! /* ! * If the request returns an error then we need to do a diag ! * reset ! */ printf("%s: page read with error; iocstatus = 0x%x\n", __func__, ioc_status); error = ENXIO; *************** *** 1046,1051 **** --- 1117,1127 ---- request->Header.PageVersion = MPI2_RAIDVOLPAGE0_PAGEVERSION; cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; cm->cm_data = NULL; + + /* + * This page must be polled because the IOC isn't ready yet when this + * page is needed. + */ error = mps_request_polled(sc, cm); reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; if (error || (reply == NULL)) { *************** *** 1099,1104 **** --- 1175,1184 ---- } cm->cm_data = page; + /* + * This page must be polled because the IOC isn't ready yet when this + * page is needed. + */ error = mps_request_polled(sc, cm); reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; if (error || (reply == NULL)) { *************** *** 1166,1177 **** request->Header.PageVersion = MPI2_RAIDVOLPAGE1_PAGEVERSION; cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; cm->cm_data = NULL; ! error = mps_request_polled(sc, cm); reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; if (error || (reply == NULL)) { /* FIXME */ ! /* If the poll returns error then we need to do diag reset */ ! printf("%s: poll for header completed with error %d", __func__, error); error = ENXIO; goto out; --- 1246,1260 ---- request->Header.PageVersion = MPI2_RAIDVOLPAGE1_PAGEVERSION; cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; cm->cm_data = NULL; ! error = mps_wait_command(sc, cm, 60, CAN_SLEEP); reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; if (error || (reply == NULL)) { /* FIXME */ ! /* ! * If the request returns an error then we need to do a diag ! * reset ! */ ! printf("%s: request for header completed with error %d", __func__, error); error = ENXIO; goto out; *************** *** 1180,1186 **** bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { /* FIXME */ ! /* If the poll returns error then we need to do diag reset */ printf("%s: header read with error; iocstatus = 0x%x\n", __func__, ioc_status); error = ENXIO; --- 1263,1272 ---- bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { /* FIXME */ ! /* ! * If the request returns an error then we need to do a diag ! * reset ! */ printf("%s: header read with error; iocstatus = 0x%x\n", __func__, ioc_status); error = ENXIO; *************** *** 1219,1230 **** } cm->cm_data = page; ! error = mps_request_polled(sc, cm); reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; if (error || (reply == NULL)) { /* FIXME */ ! /* If the poll returns error then we need to do diag reset */ ! printf("%s: poll for page completed with error %d", __func__, error); error = ENXIO; goto out; --- 1305,1319 ---- } cm->cm_data = page; ! error = mps_wait_command(sc, cm, 60, CAN_SLEEP); reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; if (error || (reply == NULL)) { /* FIXME */ ! /* ! * If the request returns an error then we need to do a diag ! * reset ! */ ! printf("%s: request for page completed with error %d", __func__, error); error = ENXIO; goto out; *************** *** 1233,1239 **** bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { /* FIXME */ ! /* If the poll returns error then we need to do diag reset */ printf("%s: page read with error; iocstatus = 0x%x\n", __func__, ioc_status); error = ENXIO; --- 1322,1331 ---- bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { /* FIXME */ ! /* ! * If the request returns an error then we need to do a diag ! * reset ! */ printf("%s: page read with error; iocstatus = 0x%x\n", __func__, ioc_status); error = ENXIO; *************** *** 1311,1316 **** --- 1403,1413 ---- request->Header.PageVersion = MPI2_RAIDPHYSDISKPAGE0_PAGEVERSION; cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; cm->cm_data = NULL; + + /* + * This page must be polled because the IOC isn't ready yet when this + * page is needed. + */ error = mps_request_polled(sc, cm); reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; if (error || (reply == NULL)) { *************** *** 1364,1369 **** --- 1461,1470 ---- } cm->cm_data = page; + /* + * This page must be polled because the IOC isn't ready yet when this + * page is needed. + */ error = mps_request_polled(sc, cm); reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; if (error || (reply == NULL)) { *** src/sys/dev/mps/mps_mapping.c.orig --- src/sys/dev/mps/mps_mapping.c *************** *** 1216,1227 **** phy_change->is_processed = 1; } else { phy_change->is_processed = 1; ! printf("%s: failed to add the " ! "device with handle 0x%04x " ! "to persistent table " ! "because there is no free " ! "space available\n", ! __func__, phy_change->dev_handle); } } else { --- 1216,1227 ---- phy_change->is_processed = 1; } else { phy_change->is_processed = 1; ! mps_dprint(sc, MPS_INFO, "%s: " ! "failed to add the device " ! "with handle 0x%04x to " ! "persistent table because " ! "there is no free space " ! "available\n", __func__, phy_change->dev_handle); } } else { *************** *** 1318,1329 **** phy_change->is_processed = 1; } else if (dpm_idx == MPS_DPM_BAD_IDX) { phy_change->is_processed = 1; ! printf("%s: failed to add the " ! "device with handle 0x%04x " ! "to persistent table " ! "because there is no free " ! "space available\n", ! __func__, phy_change->dev_handle); } } --- 1318,1329 ---- phy_change->is_processed = 1; } else if (dpm_idx == MPS_DPM_BAD_IDX) { phy_change->is_processed = 1; ! mps_dprint(sc, MPS_INFO, "%s: " ! "failed to add the device " ! "with handle 0x%04x to " ! "persistent table because " ! "there is no free space " ! "available\n", __func__, phy_change->dev_handle); } } *** src/sys/dev/mps/mps_sas.c.orig --- src/sys/dev/mps/mps_sas.c *************** *** 136,149 **** static void mpssas_resetdev_complete(struct mps_softc *, struct mps_command *); static int mpssas_send_abort(struct mps_softc *sc, struct mps_command *tm, struct mps_command *cm); static int mpssas_send_reset(struct mps_softc *sc, struct mps_command *tm, uint8_t type); - static void mpssas_rescan(struct mpssas_softc *sassc, union ccb *ccb); - static void mpssas_rescan_done(struct cam_periph *periph, union ccb *done_ccb); - static void mpssas_scanner_thread(void *arg); - #if __FreeBSD_version >= 1000006 static void mpssas_async(void *callback_arg, uint32_t code, struct cam_path *path, void *arg); ! #else ! static void mpssas_check_eedp(struct mpssas_softc *sassc); static void mpssas_read_cap_done(struct cam_periph *periph, union ccb *done_ccb); #endif static int mpssas_send_portenable(struct mps_softc *sc); --- 136,147 ---- static void mpssas_resetdev_complete(struct mps_softc *, struct mps_command *); static int mpssas_send_abort(struct mps_softc *sc, struct mps_command *tm, struct mps_command *cm); static int mpssas_send_reset(struct mps_softc *sc, struct mps_command *tm, uint8_t type); static void mpssas_async(void *callback_arg, uint32_t code, struct cam_path *path, void *arg); ! #if (__FreeBSD_version < 901503) || \ ! ((__FreeBSD_version >= 1000000) && (__FreeBSD_version < 1000006)) ! static void mpssas_check_eedp(struct mps_softc *sc, struct cam_path *path, ! struct ccb_getdev *cgd); static void mpssas_read_cap_done(struct cam_periph *periph, union ccb *done_ccb); #endif static int mpssas_send_portenable(struct mps_softc *sc); *************** *** 198,205 **** --- 196,208 ---- mps_dprint(sassc->sc, MPS_INFO, "%s releasing simq\n", __func__); sassc->flags &= ~MPSSAS_IN_STARTUP; + #if (__FreeBSD_version >= 1000036) || \ + ((__FreeBSD_version < 1000000) && (__FreeBSD_version >= 9010506)) + xpt_release_boot(); + #else xpt_release_simq(sassc->sim, 1); mpssas_rescan_target(sassc->sc, NULL); + #endif } mps_dprint(sassc->sc, MPS_TRACE, "%s refcount %u\n", __func__, sassc->startup_refcount); *************** *** 247,253 **** mps_free_high_priority_command(sc, tm); } - void mpssas_rescan_target(struct mps_softc *sc, struct mpssas_target *targ) { --- 250,255 ---- *************** *** 272,278 **** } if (xpt_create_path(&ccb->ccb_h.path, xpt_periph, pathid, ! targetid, CAM_LUN_WILDCARD) != CAM_REQ_CMP) { mps_dprint(sc, MPS_FAULT, "unable to create path for rescan\n"); xpt_free_ccb(ccb); return; --- 274,280 ---- } if (xpt_create_path(&ccb->ccb_h.path, xpt_periph, pathid, ! targetid, CAM_LUN_WILDCARD) != CAM_REQ_CMP) { mps_dprint(sc, MPS_FAULT, "unable to create path for rescan\n"); xpt_free_ccb(ccb); return; *************** *** 284,290 **** ccb->ccb_h.func_code = XPT_SCAN_TGT; mps_dprint(sc, MPS_TRACE, "%s targetid %u\n", __func__, targetid); ! mpssas_rescan(sassc, ccb); } static void --- 286,292 ---- ccb->ccb_h.func_code = XPT_SCAN_TGT; mps_dprint(sc, MPS_TRACE, "%s targetid %u\n", __func__, targetid); ! xpt_rescan(ccb); } static void *************** *** 671,679 **** mps_attach_sas(struct mps_softc *sc) { struct mpssas_softc *sassc; - #if __FreeBSD_version >= 1000006 cam_status status; - #endif int unit, error = 0; mps_dprint(sc, MPS_TRACE, "%s\n", __func__); --- 673,679 ---- *************** *** 721,736 **** taskqueue_start_threads(&sassc->ev_tq, 1, 255, "%s taskq", device_get_nameunit(sc->mps_dev)); - TAILQ_INIT(&sassc->ccb_scanq); - error = mps_kproc_create(mpssas_scanner_thread, sassc, - &sassc->rescan_thread, 0, 0, "mps_scan%d", unit); - if (error) { - mps_printf(sc, "Error %d starting rescan thread\n", error); - goto out; - } - mps_lock(sc); - sassc->flags |= MPSSAS_SCANTHREAD; /* * XXX There should be a bus for every port on the adapter, but since --- 721,727 ---- *************** *** 745,756 **** } /* ! * Assume that discovery events will start right away. Freezing ! * the simq will prevent the CAM boottime scanner from running ! * before discovery is complete. */ sassc->flags |= MPSSAS_IN_STARTUP | MPSSAS_IN_DISCOVERY; xpt_freeze_simq(sassc->sim, 1); sc->sassc->startup_refcount = 0; callout_init(&sassc->discovery_callout, 1 /*mpsafe*/); --- 736,752 ---- } /* ! * Assume that discovery events will start right away. ! * ! * Hold off boot until discovery is complete. */ sassc->flags |= MPSSAS_IN_STARTUP | MPSSAS_IN_DISCOVERY; + #if (__FreeBSD_version >= 1000036) || \ + ((__FreeBSD_version < 1000000) && (__FreeBSD_version >= 9010506)) + xpt_hold_boot(); + #else xpt_freeze_simq(sassc->sim, 1); + #endif sc->sassc->startup_refcount = 0; callout_init(&sassc->discovery_callout, 1 /*mpsafe*/); *************** *** 758,770 **** sassc->tm_count = 0; ! #if __FreeBSD_version >= 1000006 ! status = xpt_register_async(AC_ADVINFO_CHANGED, mpssas_async, sc, NULL); if (status != CAM_REQ_CMP) { ! mps_printf(sc, "Error %#x registering async handler for " ! "AC_ADVINFO_CHANGED events\n", status); } - #endif mps_unlock(sc); --- 754,794 ---- sassc->tm_count = 0; ! /* ! * Register for async events so we can determine the EEDP ! * capabilities of devices. ! */ ! status = xpt_create_path(&sassc->path, /*periph*/NULL, ! cam_sim_path(sc->sassc->sim), CAM_TARGET_WILDCARD, ! CAM_LUN_WILDCARD); ! if (status != CAM_REQ_CMP) { ! mps_printf(sc, "Error %#x creating sim path\n", status); ! sassc->path = NULL; ! } else { ! int event; ! ! #if (__FreeBSD_version >= 1000006) || \ ! ((__FreeBSD_version >= 901503) && (__FreeBSD_version < 1000000)) ! event = AC_ADVINFO_CHANGED; ! #else ! event = AC_FOUND_DEVICE; ! #endif ! status = xpt_register_async(event, mpssas_async, sc, ! sassc->path); ! if (status != CAM_REQ_CMP) { ! mps_printf(sc, "Error %#x registering async handler " ! "for event type 0x%x\n", status, event); ! xpt_free_path(sassc->path); ! sassc->path = NULL; ! } ! } if (status != CAM_REQ_CMP) { ! /* ! * EEDP use is the exception, not the rule. ! * Warn the user, but do not fail to attach. ! */ ! mps_printf(sc, "EEDP capabilities disabled.\n"); } mps_unlock(sc); *************** *** 803,811 **** mps_lock(sc); /* Deregister our async handler */ ! #if __FreeBSD_version >= 1000006 ! xpt_register_async(0, mpssas_async, sc, NULL); ! #endif if (sassc->flags & MPSSAS_IN_STARTUP) xpt_release_simq(sassc->sim, 1); --- 827,837 ---- mps_lock(sc); /* Deregister our async handler */ ! if (sassc->path != NULL) { ! xpt_register_async(0, mpssas_async, sc, sassc->path); ! xpt_free_path(sassc->path); ! sassc->path = NULL; ! } if (sassc->flags & MPSSAS_IN_STARTUP) xpt_release_simq(sassc->sim, 1); *************** *** 815,829 **** cam_sim_free(sassc->sim, FALSE); } ! if (sassc->flags & MPSSAS_SCANTHREAD) { ! sassc->flags |= MPSSAS_SHUTDOWN; ! wakeup(&sassc->ccb_scanq); ! ! if (sassc->flags & MPSSAS_SCANTHREAD) { ! msleep(&sassc->flags, &sc->mps_mtx, PRIBIO, ! "mps_shutdown", 30 * hz); ! } ! } mps_unlock(sc); mps_dprint(sc, MPS_INFO, "%s:%d\n", __func__,__LINE__); --- 841,847 ---- cam_sim_free(sassc->sim, FALSE); } ! sassc->flags |= MPSSAS_SHUTDOWN; mps_unlock(sc); mps_dprint(sc, MPS_INFO, "%s:%d\n", __func__,__LINE__); *************** *** 914,920 **** --- 932,943 ---- cpi->version_num = 1; cpi->hba_inquiry = PI_SDTR_ABLE|PI_TAG_ABLE|PI_WIDE_16; cpi->target_sprt = 0; + #if (__FreeBSD_version >= 1000036) || \ + ((__FreeBSD_version < 1000000) && (__FreeBSD_version >= 9010506)) + cpi->hba_misc = PIM_NOBUSRESET | PIM_UNMAPPED | PIM_NOSCAN; + #else cpi->hba_misc = PIM_NOBUSRESET | PIM_UNMAPPED; + #endif cpi->hba_eng_cnt = 0; cpi->max_target = sassc->sc->facts->MaxTargets - 1; cpi->max_lun = 255; *************** *** 1580,1586 **** csio = &ccb->csio; targ = &sassc->targets[csio->ccb_h.target_id]; ! mps_dprint(sc, MPS_TRACE, "%s ccb %p target flag %x\n", __func__, ccb, targ->flags); if (targ->handle == 0x0) { mps_dprint(sc, MPS_TRACE, "%s NULL handle for target %u\n", __func__, csio->ccb_h.target_id); --- 1603,1610 ---- csio = &ccb->csio; targ = &sassc->targets[csio->ccb_h.target_id]; ! mps_dprint(sc, MPS_TRACE, "%s ccb %p target flag %x\n", __func__, ccb, ! targ->flags); if (targ->handle == 0x0) { mps_dprint(sc, MPS_TRACE, "%s NULL handle for target %u\n", __func__, csio->ccb_h.target_id); *************** *** 1589,1601 **** return; } if (targ->flags & MPS_TARGET_FLAGS_RAID_COMPONENT) { ! mps_dprint(sc, MPS_TRACE, "%s Raid component no SCSI IO supported %u\n", ! __func__, csio->ccb_h.target_id); csio->ccb_h.status = CAM_TID_INVALID; xpt_done(ccb); return; } /* * If devinfo is 0 this will be a volume. In that case don't tell CAM * that the volume has timed out. We want volumes to be enumerated * until they are deleted/removed, not just failed. --- 1613,1636 ---- return; } if (targ->flags & MPS_TARGET_FLAGS_RAID_COMPONENT) { ! mps_dprint(sc, MPS_TRACE, "%s Raid component no SCSI IO " ! "supported %u\n", __func__, csio->ccb_h.target_id); csio->ccb_h.status = CAM_TID_INVALID; xpt_done(ccb); return; } /* + * Sometimes, it is possible to get a command that is not "In + * Progress" and was actually aborted by the upper layer. Check for + * this here and complete the command without error. + */ + if (ccb->ccb_h.status != CAM_REQ_INPROG) { + mps_dprint(sc, MPS_TRACE, "%s Command is not in progress for " + "target %u\n", __func__, csio->ccb_h.target_id); + xpt_done(ccb); + return; + } + /* * If devinfo is 0 this will be a volume. In that case don't tell CAM * that the volume has timed out. We want volumes to be enumerated * until they are deleted/removed, not just failed. *************** *** 1663,1669 **** break; } ! if (csio->cdb_len == 32) mpi_control |= 4 << MPI2_SCSIIO_CONTROL_ADDCDBLEN_SHIFT; /* * It looks like the hardware doesn't require an explicit tag --- 1698,1704 ---- break; } ! if (csio->cdb_len == 32) mpi_control |= 4 << MPI2_SCSIIO_CONTROL_ADDCDBLEN_SHIFT; /* * It looks like the hardware doesn't require an explicit tag *************** *** 1791,1796 **** --- 1826,1832 ---- targ->issued++; targ->outstanding++; TAILQ_INSERT_TAIL(&targ->commands, cm, cm_link); + ccb->ccb_h.status |= CAM_SIM_QUEUED; if ((sc->mps_debug & MPS_TRACE) != 0) mpssas_log_command(cm, "%s cm %p ccb %p outstanding %u\n", *************** *** 1969,1982 **** strcat(desc_scsi_state, "autosense valid "); mps_dprint(sc, MPS_INFO, "\thandle(0x%04x), ioc_status(%s)(0x%04x), \n", ! le16toh(mpi_reply->DevHandle), ! desc_ioc_state, ioc_status); /* We can add more detail about underflow data here * TO-DO * */ mps_dprint(sc, MPS_INFO, "\tscsi_status(%s)(0x%02x), " ! "scsi_state(%s)(0x%02x)\n", desc_scsi_status, ! scsi_status, desc_scsi_state, scsi_state); if (sc->mps_debug & MPS_INFO && scsi_state & MPI2_SCSI_STATE_AUTOSENSE_VALID) { --- 2005,2017 ---- strcat(desc_scsi_state, "autosense valid "); mps_dprint(sc, MPS_INFO, "\thandle(0x%04x), ioc_status(%s)(0x%04x), \n", ! le16toh(mpi_reply->DevHandle), desc_ioc_state, ioc_status); /* We can add more detail about underflow data here * TO-DO * */ mps_dprint(sc, MPS_INFO, "\tscsi_status(%s)(0x%02x), " ! "scsi_state(%s)(0x%02x)\n", desc_scsi_status, scsi_status, ! desc_scsi_state, scsi_state); if (sc->mps_debug & MPS_INFO && scsi_state & MPI2_SCSI_STATE_AUTOSENSE_VALID) { *************** *** 2033,2038 **** --- 2068,2074 ---- cm->cm_targ->completed++; cm->cm_targ->outstanding--; TAILQ_REMOVE(&cm->cm_targ->commands, cm, cm_link); + ccb->ccb_h.status |= ~(CAM_STATUS_MASK | CAM_SIM_QUEUED); if (cm->cm_state == MPS_CM_STATE_TIMEDOUT) { TAILQ_REMOVE(&cm->cm_targ->timedout_commands, cm, cm_recovery); *************** *** 2108,2114 **** ccb->ccb_h.status |= CAM_RELEASE_SIMQ; sassc->flags &= ~MPSSAS_QUEUE_FROZEN; mps_dprint(sc, MPS_INFO, ! "Unfreezing SIM queue\n"); } } --- 2144,2150 ---- ccb->ccb_h.status |= CAM_RELEASE_SIMQ; sassc->flags &= ~MPSSAS_QUEUE_FROZEN; mps_dprint(sc, MPS_INFO, ! "Unfreezing SIM queue\n"); } } *************** *** 2335,2341 **** ccb->ccb_h.status |= CAM_RELEASE_SIMQ; sassc->flags &= ~MPSSAS_QUEUE_FROZEN; mps_dprint(sc, MPS_INFO, "Command completed, " ! "unfreezing SIM queue\n"); } if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) { --- 2371,2377 ---- ccb->ccb_h.status |= CAM_RELEASE_SIMQ; sassc->flags &= ~MPSSAS_QUEUE_FROZEN; mps_dprint(sc, MPS_INFO, "Command completed, " ! "unfreezing SIM queue\n"); } if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) { *************** *** 2651,2657 **** sasaddr = le32toh(req->SASAddress.Low); sasaddr |= ((uint64_t)(le32toh(req->SASAddress.High))) << 32; ! if ((le16toh(rpl->IOCStatus) & MPI2_IOCSTATUS_MASK) != MPI2_IOCSTATUS_SUCCESS || rpl->SASStatus != MPI2_SASSTATUS_SUCCESS) { mps_dprint(sc, MPS_INFO, "%s: IOCStatus %04x SASStatus %02x\n", __func__, le16toh(rpl->IOCStatus), rpl->SASStatus); --- 2687,2694 ---- sasaddr = le32toh(req->SASAddress.Low); sasaddr |= ((uint64_t)(le32toh(req->SASAddress.High))) << 32; ! if ((le16toh(rpl->IOCStatus) & MPI2_IOCSTATUS_MASK) != ! MPI2_IOCSTATUS_SUCCESS || rpl->SASStatus != MPI2_SASSTATUS_SUCCESS) { mps_dprint(sc, MPS_INFO, "%s: IOCStatus %04x SASStatus %02x\n", __func__, le16toh(rpl->IOCStatus), rpl->SASStatus); *************** *** 2774,2780 **** MPI2_SGLFLAGS_SYSTEM_ADDRESS_SPACE | MPI2_SGLFLAGS_SGL_TYPE_MPI; mps_dprint(sc, MPS_INFO, "%s: sending SMP request to SAS " ! "address %#jx\n", __func__, (uintmax_t)sasaddr); mpi_init_sge(cm, req, &req->SGL); --- 2811,2817 ---- MPI2_SGLFLAGS_SYSTEM_ADDRESS_SPACE | MPI2_SGLFLAGS_SGL_TYPE_MPI; mps_dprint(sc, MPS_INFO, "%s: sending SMP request to SAS " ! "address %#jx\n", __func__, (uintmax_t)sasaddr); mpi_init_sge(cm, req, &req->SGL); *************** *** 2992,2998 **** sc = sassc->sc; tm = mps_alloc_command(sc); if (tm == NULL) { ! mps_printf(sc, "comand alloc failure in mpssas_action_resetdev\n"); ccb->ccb_h.status = CAM_RESRC_UNAVAIL; xpt_done(ccb); return; --- 3029,3036 ---- sc = sassc->sc; tm = mps_alloc_command(sc); if (tm == NULL) { ! mps_printf(sc, "comand alloc failure in " ! "mpssas_action_resetdev\n"); ccb->ccb_h.status = CAM_RESRC_UNAVAIL; xpt_done(ccb); return; *************** *** 3080,3193 **** } static void - mpssas_rescan_done(struct cam_periph *periph, union ccb *done_ccb) - { - struct mpssas_softc *sassc; - char path_str[64]; - - if (done_ccb == NULL) - return; - - sassc = (struct mpssas_softc *)done_ccb->ccb_h.ppriv_ptr1; - - mtx_assert(&sassc->sc->mps_mtx, MA_OWNED); - - xpt_path_string(done_ccb->ccb_h.path, path_str, sizeof(path_str)); - mps_dprint(sassc->sc, MPS_INFO, "Completing rescan for %s\n", path_str); - - xpt_free_path(done_ccb->ccb_h.path); - xpt_free_ccb(done_ccb); - - #if __FreeBSD_version < 1000006 - /* - * Before completing scan, get EEDP stuff for all of the existing - * targets. - */ - mpssas_check_eedp(sassc); - #endif - - } - - /* thread to handle bus rescans */ - static void - mpssas_scanner_thread(void *arg) - { - struct mpssas_softc *sassc; - struct mps_softc *sc; - union ccb *ccb; - - sassc = (struct mpssas_softc *)arg; - sc = sassc->sc; - - mps_dprint(sc, MPS_TRACE, "%s\n", __func__); - - mps_lock(sc); - for (;;) { - /* Sleep for 1 second and check the queue status*/ - msleep(&sassc->ccb_scanq, &sc->mps_mtx, PRIBIO, - "mps_scanq", 1 * hz); - if (sassc->flags & MPSSAS_SHUTDOWN) { - mps_dprint(sc, MPS_TRACE, "Scanner shutting down\n"); - break; - } - next_work: - // Get first work. - ccb = (union ccb *)TAILQ_FIRST(&sassc->ccb_scanq); - if (ccb == NULL) - continue; - // Got first work. - TAILQ_REMOVE(&sassc->ccb_scanq, &ccb->ccb_h, sim_links.tqe); - xpt_action(ccb); - if (sassc->flags & MPSSAS_SHUTDOWN) { - mps_dprint(sc, MPS_TRACE, "Scanner shutting down\n"); - break; - } - goto next_work; - } - - sassc->flags &= ~MPSSAS_SCANTHREAD; - wakeup(&sassc->flags); - mps_unlock(sc); - mps_dprint(sc, MPS_TRACE, "Scanner exiting\n"); - mps_kproc_exit(0); - } - - /* - * This function will send READ_CAP_16 to find out EEDP protection mode. - * It will check inquiry data before sending READ_CAP_16. - * Callback for READ_CAP_16 is "mpssas_read_cap_done". - * This is insternal scsi command and we need to take care release of devq, if - * CAM_DEV_QFRZN is set. Driver needs to release devq if it has frozen any. - * xpt_release_devq is called from mpssas_read_cap_done. - * - * All other commands will be handled by periph layer and there it will - * check for "CAM_DEV_QFRZN" and release of devq will be done. - */ - static void - mpssas_rescan(struct mpssas_softc *sassc, union ccb *ccb) - { - char path_str[64]; - - mps_dprint(sassc->sc, MPS_TRACE, "%s\n", __func__); - - mtx_assert(&sassc->sc->mps_mtx, MA_OWNED); - - if (ccb == NULL) - return; - - xpt_path_string(ccb->ccb_h.path, path_str, sizeof(path_str)); - mps_dprint(sassc->sc, MPS_INFO, "Queueing rescan for %s\n", path_str); - - /* Prepare request */ - ccb->ccb_h.ppriv_ptr1 = sassc; - ccb->ccb_h.cbfcnp = mpssas_rescan_done; - xpt_setup_ccb(&ccb->ccb_h, ccb->ccb_h.path, MPS_PRIORITY_XPT); - TAILQ_INSERT_TAIL(&sassc->ccb_scanq, &ccb->ccb_h, sim_links.tqe); - wakeup(&sassc->ccb_scanq); - } - - #if __FreeBSD_version >= 1000006 - static void mpssas_async(void *callback_arg, uint32_t code, struct cam_path *path, void *arg) { --- 3118,3123 ---- *************** *** 3196,3201 **** --- 3126,3133 ---- sc = (struct mps_softc *)callback_arg; switch (code) { + #if (__FreeBSD_version >= 1000006) || \ + ((__FreeBSD_version >= 901503) && (__FreeBSD_version < 1000000)) case AC_ADVINFO_CHANGED: { struct mpssas_target *target; struct mpssas_softc *sassc; *************** *** 3218,3230 **** break; /* - * We're only interested in devices that are attached to - * this controller. - */ - if (xpt_path_path_id(path) != sassc->sim->path_id) - break; - - /* * We should have a handle for this, but check to make sure. */ target = &sassc->targets[xpt_path_target_id(path)]; --- 3150,3155 ---- *************** *** 3275,3452 **** } break; } default: break; } } - #else /* __FreeBSD_version >= 1000006 */ static void ! mpssas_check_eedp(struct mpssas_softc *sassc) { ! struct mps_softc *sc = sassc->sc; struct ccb_scsiio *csio; struct scsi_read_capacity_16 *scsi_cmd; struct scsi_read_capacity_eedp *rcap_buf; ! union ccb *ccb; ! path_id_t pathid = cam_sim_path(sassc->sim); target_id_t targetid; lun_id_t lunid; ! struct cam_periph *found_periph; struct mpssas_target *target; struct mpssas_lun *lun; uint8_t found_lun; - struct ccb_getdev cgd; char path_str[64]; /* ! * Issue a READ CAPACITY 16 command to each LUN of each target. This ! * info is used to determine if the LUN is formatted for EEDP support. */ ! for (targetid = 0; targetid < sc->facts->MaxTargets; targetid++) { ! target = &sassc->targets[targetid]; ! if (target->handle == 0x0) { ! continue; ! } ! lunid = 0; ! do { ! ccb = xpt_alloc_ccb_nowait(); ! if (ccb == NULL) { ! mps_dprint(sc, MPS_FAULT, "Unable to alloc CCB " ! "for EEDP support.\n"); ! return; ! } ! if (xpt_create_path(&ccb->ccb_h.path, xpt_periph, ! pathid, targetid, lunid) != CAM_REQ_CMP) { ! mps_dprint(sc, MPS_FAULT, "Unable to create " ! "path for EEDP support\n"); ! xpt_free_ccb(ccb); ! return; ! } ! /* ! * If a periph is returned, the LUN exists. Create an ! * entry in the target's LUN list. ! */ ! if ((found_periph = cam_periph_find(ccb->ccb_h.path, ! NULL)) != NULL) { ! /* ! * If LUN is already in list, don't create a new ! * one. ! */ ! found_lun = FALSE; ! SLIST_FOREACH(lun, &target->luns, lun_link) { ! if (lun->lun_id == lunid) { ! found_lun = TRUE; ! break; ! } ! } ! if (!found_lun) { ! lun = malloc(sizeof(struct mpssas_lun), ! M_MPT2, M_NOWAIT | M_ZERO); ! if (lun == NULL) { ! mps_dprint(sc, MPS_FAULT, ! "Unable to alloc LUN for " ! "EEDP support.\n"); ! xpt_free_path(ccb->ccb_h.path); ! xpt_free_ccb(ccb); ! return; ! } ! lun->lun_id = lunid; ! SLIST_INSERT_HEAD(&target->luns, lun, ! lun_link); ! } ! lunid++; ! /* Before Issuing READ CAPACITY 16, ! * check Device type. ! */ ! xpt_setup_ccb(&cgd.ccb_h, ccb->ccb_h.path, ! CAM_PRIORITY_NORMAL); ! cgd.ccb_h.func_code = XPT_GDEV_TYPE; ! xpt_action((union ccb *)&cgd); ! /* ! * If this flag is set in the inquiry data, ! * the device supports protection information, ! * and must support the 16 byte read ! * capacity command, otherwise continue without ! * sending read cap 16 ! */ ! xpt_path_string(ccb->ccb_h.path, path_str, ! sizeof(path_str)); ! if ((cgd.inq_data.spc3_flags & ! SPC3_SID_PROTECT) == 0) { ! xpt_free_path(ccb->ccb_h.path); ! xpt_free_ccb(ccb); ! continue; ! } ! ! mps_dprint(sc, MPS_INFO, ! "Sending read cap: path %s" ! " handle %d\n", path_str, target->handle ); ! ! /* ! * Issue a READ CAPACITY 16 command for the LUN. ! * The mpssas_read_cap_done function will load ! * the read cap info into the LUN struct. ! */ ! rcap_buf = ! malloc(sizeof(struct scsi_read_capacity_eedp), ! M_MPT2, M_NOWAIT| M_ZERO); ! if (rcap_buf == NULL) { ! mps_dprint(sc, MPS_FAULT, "Unable to alloc read " ! "capacity buffer for EEDP support.\n"); ! xpt_free_path(ccb->ccb_h.path); ! xpt_free_ccb(ccb); ! return; ! } ! csio = &ccb->csio; ! csio->ccb_h.func_code = XPT_SCSI_IO; ! csio->ccb_h.flags = CAM_DIR_IN; ! csio->ccb_h.retry_count = 4; ! csio->ccb_h.cbfcnp = mpssas_read_cap_done; ! csio->ccb_h.timeout = 60000; ! csio->data_ptr = (uint8_t *)rcap_buf; ! csio->dxfer_len = sizeof(struct ! scsi_read_capacity_eedp); ! csio->sense_len = MPS_SENSE_LEN; ! csio->cdb_len = sizeof(*scsi_cmd); ! csio->tag_action = MSG_SIMPLE_Q_TAG; ! scsi_cmd = (struct scsi_read_capacity_16 *) ! &csio->cdb_io.cdb_bytes; ! bzero(scsi_cmd, sizeof(*scsi_cmd)); ! scsi_cmd->opcode = 0x9E; ! scsi_cmd->service_action = SRC16_SERVICE_ACTION; ! ((uint8_t *)scsi_cmd)[13] = sizeof(struct ! scsi_read_capacity_eedp); ! ! /* ! * Set the path, target and lun IDs for the READ ! * CAPACITY request. ! */ ! ccb->ccb_h.path_id = ! xpt_path_path_id(ccb->ccb_h.path); ! ccb->ccb_h.target_id = ! xpt_path_target_id(ccb->ccb_h.path); ! ccb->ccb_h.target_lun = ! xpt_path_lun_id(ccb->ccb_h.path); ! ! ccb->ccb_h.ppriv_ptr1 = sassc; ! xpt_action(ccb); ! } else { ! xpt_free_path(ccb->ccb_h.path); ! xpt_free_ccb(ccb); ! } ! } while (found_periph); ! } } - static void mpssas_read_cap_done(struct cam_periph *periph, union ccb *done_ccb) { --- 3200,3347 ---- } break; } + #else + case AC_FOUND_DEVICE: { + struct ccb_getdev *cgd; + + cgd = arg; + mpssas_check_eedp(sc, path, cgd); + break; + } + #endif default: break; } } + #if (__FreeBSD_version < 901503) || \ + ((__FreeBSD_version >= 1000000) && (__FreeBSD_version < 1000006)) static void ! mpssas_check_eedp(struct mps_softc *sc, struct cam_path *path, ! struct ccb_getdev *cgd) { ! struct mpssas_softc *sassc = sc->sassc; struct ccb_scsiio *csio; struct scsi_read_capacity_16 *scsi_cmd; struct scsi_read_capacity_eedp *rcap_buf; ! path_id_t pathid; target_id_t targetid; lun_id_t lunid; ! union ccb *ccb; ! struct cam_path *local_path; struct mpssas_target *target; struct mpssas_lun *lun; uint8_t found_lun; char path_str[64]; + sassc = sc->sassc; + pathid = cam_sim_path(sassc->sim); + targetid = xpt_path_target_id(path); + lunid = xpt_path_lun_id(path); + + target = &sassc->targets[targetid]; + if (target->handle == 0x0) + return; + /* ! * Determine if the device is EEDP capable. ! * ! * If this flag is set in the inquiry data, ! * the device supports protection information, ! * and must support the 16 byte read ! * capacity command, otherwise continue without ! * sending read cap 16 */ ! if ((cgd->inq_data.spc3_flags & SPC3_SID_PROTECT) == 0) ! return; ! /* ! * Issue a READ CAPACITY 16 command. This info ! * is used to determine if the LUN is formatted ! * for EEDP support. ! */ ! ccb = xpt_alloc_ccb_nowait(); ! if (ccb == NULL) { ! mps_dprint(sc, MPS_FAULT, ! "Unable to alloc CCB for EEDP support.\n"); ! return; ! } ! if (xpt_create_path(&local_path, xpt_periph, ! pathid, targetid, lunid) != CAM_REQ_CMP) { ! mps_dprint(sc, MPS_FAULT, ! "Unable to create path for EEDP support\n"); ! xpt_free_ccb(ccb); ! return; ! } ! /* ! * If LUN is already in list, don't create a new ! * one. ! */ ! found_lun = FALSE; ! SLIST_FOREACH(lun, &target->luns, lun_link) { ! if (lun->lun_id == lunid) { ! found_lun = TRUE; ! break; ! } ! } ! if (!found_lun) { ! lun = malloc(sizeof(struct mpssas_lun), M_MPT2, ! M_NOWAIT | M_ZERO); ! if (lun == NULL) { ! mps_dprint(sc, MPS_FAULT, ! "Unable to alloc LUN for EEDP support.\n"); ! xpt_free_path(local_path); ! xpt_free_ccb(ccb); ! return; ! } ! lun->lun_id = lunid; ! SLIST_INSERT_HEAD(&target->luns, lun, ! lun_link); ! } ! xpt_path_string(local_path, path_str, sizeof(path_str)); ! mps_dprint(sc, MPS_INFO, "Sending read cap: path %s handle %d\n", ! path_str, target->handle); ! /* ! * Issue a READ CAPACITY 16 command for the LUN. ! * The mpssas_read_cap_done function will load ! * the read cap info into the LUN struct. ! */ ! rcap_buf = malloc(sizeof(struct scsi_read_capacity_eedp), ! M_MPT2, M_NOWAIT | M_ZERO); ! if (rcap_buf == NULL) { ! mps_dprint(sc, MPS_FAULT, ! "Unable to alloc read capacity buffer for EEDP support.\n"); ! xpt_free_path(ccb->ccb_h.path); ! xpt_free_ccb(ccb); ! return; ! } ! xpt_setup_ccb(&ccb->ccb_h, local_path, CAM_PRIORITY_XPT); ! csio = &ccb->csio; ! csio->ccb_h.func_code = XPT_SCSI_IO; ! csio->ccb_h.flags = CAM_DIR_IN; ! csio->ccb_h.retry_count = 4; ! csio->ccb_h.cbfcnp = mpssas_read_cap_done; ! csio->ccb_h.timeout = 60000; ! csio->data_ptr = (uint8_t *)rcap_buf; ! csio->dxfer_len = sizeof(struct scsi_read_capacity_eedp); ! csio->sense_len = MPS_SENSE_LEN; ! csio->cdb_len = sizeof(*scsi_cmd); ! csio->tag_action = MSG_SIMPLE_Q_TAG; ! scsi_cmd = (struct scsi_read_capacity_16 *)&csio->cdb_io.cdb_bytes; ! bzero(scsi_cmd, sizeof(*scsi_cmd)); ! scsi_cmd->opcode = 0x9E; ! scsi_cmd->service_action = SRC16_SERVICE_ACTION; ! ((uint8_t *)scsi_cmd)[13] = sizeof(struct scsi_read_capacity_eedp); ! ccb->ccb_h.ppriv_ptr1 = sassc; ! xpt_action(ccb); } static void mpssas_read_cap_done(struct cam_periph *periph, union ccb *done_ccb) { *************** *** 3499,3504 **** --- 3394,3403 ---- } if (rcap_buf->protect & 0x01) { + mps_dprint(sassc->sc, MPS_INFO, "LUN %d for " + "target ID %d is formatted for EEDP " + "support.\n", done_ccb->ccb_h.target_lun, + done_ccb->ccb_h.target_id); lun->eedp_formatted = TRUE; lun->eedp_block_size = scsi_4btoul(rcap_buf->length); } *************** *** 3510,3516 **** xpt_free_path(done_ccb->ccb_h.path); xpt_free_ccb(done_ccb); } ! #endif /* __FreeBSD_version >= 1000006 */ int mpssas_startup(struct mps_softc *sc) --- 3409,3416 ---- xpt_free_path(done_ccb->ccb_h.path); xpt_free_ccb(done_ccb); } ! #endif /* (__FreeBSD_version < 901503) || \ ! ((__FreeBSD_version >= 1000000) && (__FreeBSD_version < 1000006)) */ int mpssas_startup(struct mps_softc *sc) *** src/sys/dev/mps/mps_sas.h.orig --- src/sys/dev/mps/mps_sas.h *************** *** 87,93 **** #define MPSSAS_DISCOVERY_TIMEOUT_PENDING (1 << 2) #define MPSSAS_QUEUE_FROZEN (1 << 3) #define MPSSAS_SHUTDOWN (1 << 4) - #define MPSSAS_SCANTHREAD (1 << 5) struct mpssas_target *targets; struct cam_devq *devq; struct cam_sim *sim; --- 87,92 ---- *************** *** 101,109 **** u_int tm_count; struct proc *sysctl_proc; - TAILQ_HEAD(, ccb_hdr) ccb_scanq; - struct proc *rescan_thread; - struct taskqueue *ev_tq; struct task ev_task; TAILQ_HEAD(, mps_fw_event_work) ev_queue; --- 100,105 ---- *** src/sys/dev/mps/mps_sas_lsi.c.orig --- src/sys/dev/mps/mps_sas_lsi.c *************** *** 699,705 **** --- 699,709 ---- mps_dprint(sc, MPS_INFO, "Found device <%s> <%s> <0x%04x> <%d/%d>\n", devstring, mps_describe_table(mps_linkrate_names, targ->linkrate), targ->handle, targ->encl_handle, targ->encl_slot); + + #if ((__FreeBSD_version < 9010506) || \ + ((__FreeBSD_version >= 1000000) && (__FreeBSD_version < 1000036))) if ((sassc->flags & MPSSAS_IN_STARTUP) == 0) + #endif mpssas_rescan_target(sc, targ); mps_dprint(sc, MPS_INFO, "Target id 0x%x added\n", targ->tid); out: *************** *** 818,829 **** cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; cm->cm_data = buffer; cm->cm_length = htole32(sz); ! error = mps_request_polled(sc, cm); reply = (Mpi2SataPassthroughReply_t *)cm->cm_reply; if (error || (reply == NULL)) { /* FIXME */ ! /* If the poll returns error then we need to do diag reset */ ! printf("%s: poll for page completed with error %d", __func__, error); error = ENXIO; goto out; --- 822,836 ---- cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; cm->cm_data = buffer; cm->cm_length = htole32(sz); ! error = mps_wait_command(sc, cm, 60, CAN_SLEEP); reply = (Mpi2SataPassthroughReply_t *)cm->cm_reply; if (error || (reply == NULL)) { /* FIXME */ ! /* ! * If the request returns an error then we need to do a diag ! * reset ! */ ! printf("%s: request for page completed with error %d", __func__, error); error = ENXIO; goto out; *************** *** 955,961 **** action->Action = MPI2_RAID_ACTION_SYSTEM_SHUTDOWN_INITIATED; cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; mps_lock(sc); ! mps_request_polled(sc, cm); mps_unlock(sc); /* --- 962,968 ---- action->Action = MPI2_RAID_ACTION_SYSTEM_SHUTDOWN_INITIATED; cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; mps_lock(sc); ! mps_wait_command(sc, cm, 5, CAN_SLEEP); mps_unlock(sc); /* *** src/sys/dev/mps/mps_user.c.orig --- src/sys/dev/mps/mps_user.c *************** *** 672,678 **** cm = mps_alloc_command(sc); if (cm == NULL) { ! mps_printf(sc, "mps_user_command: no mps requests\n"); err = ENOMEM; goto Ret; } --- 672,678 ---- cm = mps_alloc_command(sc); if (cm == NULL) { ! mps_printf(sc, "%s: no mps requests\n", __func__); err = ENOMEM; goto Ret; } *************** *** 680,687 **** hdr = (MPI2_REQUEST_HEADER *)cm->cm_req; ! mps_dprint(sc, MPS_INFO, "mps_user_command: req %p %d rpl %p %d\n", ! cmd->req, cmd->req_len, cmd->rpl, cmd->rpl_len ); if (cmd->req_len > (int)sc->facts->IOCRequestFrameSize * 4) { err = EINVAL; --- 680,687 ---- hdr = (MPI2_REQUEST_HEADER *)cm->cm_req; ! mps_dprint(sc, MPS_INFO, "%s: req %p %d rpl %p %d\n", __func__, ! cmd->req, cmd->req_len, cmd->rpl, cmd->rpl_len); if (cmd->req_len > (int)sc->facts->IOCRequestFrameSize * 4) { err = EINVAL; *************** *** 691,698 **** if (err != 0) goto RetFreeUnlocked; ! mps_dprint(sc, MPS_INFO, "mps_user_command: Function %02X " ! "MsgFlags %02X\n", hdr->Function, hdr->MsgFlags ); err = mps_user_setup_request(cm, cmd); if (err != 0) { --- 691,698 ---- if (err != 0) goto RetFreeUnlocked; ! mps_dprint(sc, MPS_INFO, "%s: Function %02X MsgFlags %02X\n", __func__, ! hdr->Function, hdr->MsgFlags); err = mps_user_setup_request(cm, cmd); if (err != 0) { *************** *** 718,725 **** cm->cm_flags = MPS_CM_FLAGS_SGE_SIMPLE; cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; mps_lock(sc); ! err = mps_wait_command(sc, cm, 30); if (err) { mps_printf(sc, "%s: invalid request: error %d\n", --- 718,734 ---- cm->cm_flags = MPS_CM_FLAGS_SGE_SIMPLE; cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; + err = mps_user_setup_request(cm, cmd); + if (err == EINVAL) { + mps_printf(sc, "%s: unsupported parameter or unsupported " + "function in request (function = 0x%X)\n", __func__, + hdr->Function); + } + if (err != 0) + goto RetFreeUnlocked; + mps_lock(sc); ! err = mps_wait_command(sc, cm, 60, CAN_SLEEP); if (err) { mps_printf(sc, "%s: invalid request: error %d\n", *************** *** 731,740 **** sz = rpl->MsgLength * 4; if (sz > cmd->rpl_len) { ! mps_printf(sc, ! "mps_user_command: reply buffer too small %d required %d\n", ! cmd->rpl_len, sz ); ! err = EINVAL; sz = cmd->rpl_len; } --- 740,747 ---- sz = rpl->MsgLength * 4; if (sz > cmd->rpl_len) { ! mps_printf(sc, "%s: user reply buffer (%d) smaller than " ! "returned buffer (%d)\n", __func__, cmd->rpl_len, sz); sz = cmd->rpl_len; } *************** *** 742,748 **** copyout(rpl, cmd->rpl, sz); if (buf != NULL) copyout(buf, cmd->buf, cmd->len); ! mps_dprint(sc, MPS_INFO, "mps_user_command: reply size %d\n", sz ); RetFreeUnlocked: mps_lock(sc); --- 749,755 ---- copyout(rpl, cmd->rpl, sz); if (buf != NULL) copyout(buf, cmd->buf, cmd->len); ! mps_dprint(sc, MPS_INFO, "%s: reply size %d\n", __func__, sz); RetFreeUnlocked: mps_lock(sc); *************** *** 849,855 **** cm->cm_complete = NULL; cm->cm_complete_data = NULL; ! err = mps_wait_command(sc, cm, 30); if (err != 0) { err = EIO; --- 856,862 ---- cm->cm_complete = NULL; cm->cm_complete_data = NULL; ! err = mps_wait_command(sc, cm, 30, CAN_SLEEP); if (err != 0) { err = EIO; *************** *** 864,878 **** sz = rpl->MsgLength * 4; if (sz > data->ReplySize) { ! mps_printf(sc, "%s: reply buffer too small: %d, " ! "required: %d\n", __func__, data->ReplySize, sz); ! err = EINVAL; ! } else { ! mps_unlock(sc); ! copyout(cm->cm_reply, PTRIN(data->PtrReply), ! data->ReplySize); ! mps_lock(sc); } } mpssas_free_tm(sc, cm); goto Ret; --- 871,884 ---- sz = rpl->MsgLength * 4; if (sz > data->ReplySize) { ! mps_printf(sc, "%s: user reply buffer (%d) " ! "smaller than returned buffer (%d)\n", ! __func__, data->ReplySize, sz); } + mps_unlock(sc); + copyout(cm->cm_reply, PTRIN(data->PtrReply), + data->ReplySize); + mps_lock(sc); } mpssas_free_tm(sc, cm); goto Ret; *************** *** 986,992 **** mps_lock(sc); ! err = mps_wait_command(sc, cm, 30); if (err) { mps_printf(sc, "%s: invalid request: error %d\n", __func__, --- 992,998 ---- mps_lock(sc); ! err = mps_wait_command(sc, cm, 30, CAN_SLEEP); if (err) { mps_printf(sc, "%s: invalid request: error %d\n", __func__, *************** *** 1025,1039 **** sz = rpl->MsgLength * 4; if (sz > data->ReplySize) { ! mps_printf(sc, "%s: reply buffer too small: %d, " ! "required: %d\n", __func__, data->ReplySize, sz); ! err = EINVAL; ! } else { ! mps_unlock(sc); ! copyout(cm->cm_reply, PTRIN(data->PtrReply), ! data->ReplySize); ! mps_lock(sc); } if ((function == MPI2_FUNCTION_SCSI_IO_REQUEST) || (function == MPI2_FUNCTION_RAID_SCSI_IO_PASSTHROUGH)) { --- 1031,1043 ---- sz = rpl->MsgLength * 4; if (sz > data->ReplySize) { ! mps_printf(sc, "%s: user reply buffer (%d) smaller " ! "than returned buffer (%d)\n", __func__, ! data->ReplySize, sz); } + mps_unlock(sc); + copyout(cm->cm_reply, PTRIN(data->PtrReply), data->ReplySize); + mps_lock(sc); if ((function == MPI2_FUNCTION_SCSI_IO_REQUEST) || (function == MPI2_FUNCTION_RAID_SCSI_IO_PASSTHROUGH)) { *************** *** 1203,1209 **** /* * Send command synchronously. */ ! status = mps_wait_command(sc, cm, 30); if (status) { mps_printf(sc, "%s: invalid request: error %d\n", __func__, status); --- 1207,1213 ---- /* * Send command synchronously. */ ! status = mps_wait_command(sc, cm, 30, CAN_SLEEP); if (status) { mps_printf(sc, "%s: invalid request: error %d\n", __func__, status); *************** *** 1252,1259 **** */ *return_code = MPS_FW_DIAG_ERROR_RELEASE_FAILED; if (!pBuffer->enabled) { ! mps_dprint(sc, MPS_INFO, "%s: This buffer type is not supported " ! "by the IOC", __func__); return (MPS_DIAG_FAILURE); } --- 1256,1263 ---- */ *return_code = MPS_FW_DIAG_ERROR_RELEASE_FAILED; if (!pBuffer->enabled) { ! mps_dprint(sc, MPS_INFO, "%s: This buffer type is not " ! "supported by the IOC", __func__); return (MPS_DIAG_FAILURE); } *************** *** 1287,1293 **** /* * Send command synchronously. */ ! status = mps_wait_command(sc, cm, 30); if (status) { mps_printf(sc, "%s: invalid request: error %d\n", __func__, status); --- 1291,1297 ---- /* * Send command synchronously. */ ! status = mps_wait_command(sc, cm, 30, CAN_SLEEP); if (status) { mps_printf(sc, "%s: invalid request: error %d\n", __func__, status); *** src/sys/dev/mps/mpsvar.h.orig --- src/sys/dev/mps/mpsvar.h *************** *** 26,38 **** * * LSI MPT-Fusion Host Adapter FreeBSD * ! * $FreeBSD: stable/9/sys/dev/mps/mpsvar.h 251874 2013-06-18 00:36:53Z scottl $ */ #ifndef _MPSVAR_H #define _MPSVAR_H ! #define MPS_DRIVER_VERSION "14.00.00.01-fbsd" #define MPS_DB_MAX_WAIT 2500 --- 26,38 ---- * * LSI MPT-Fusion Host Adapter FreeBSD * ! * $FreeBSD: head/sys/dev/mps/mpsvar.h 246713 2013-02-12 16:57:20Z kib $ */ #ifndef _MPSVAR_H #define _MPSVAR_H ! #define MPS_DRIVER_VERSION "16.00.00.00-fbsd" #define MPS_DB_MAX_WAIT 2500 *************** *** 304,310 **** bus_dma_tag_t buffer_dmat; MPI2_IOC_FACTS_REPLY *facts; - MPI2_PORT_FACTS_REPLY *pfacts; int num_reqs; int num_replies; int fqdepth; /* Free queue */ --- 304,309 ---- *************** *** 628,642 **** static __inline void mps_from_u64(uint64_t data, U64 *mps) { ! (mps)->High = (uint32_t)((data) >> 32); ! (mps)->Low = (uint32_t)((data) & 0xffffffff); } static __inline uint64_t mps_to_u64(U64 *data) { ! return (((uint64_t)data->High << 32) | data->Low); } static __inline void --- 627,641 ---- static __inline void mps_from_u64(uint64_t data, U64 *mps) { ! (mps)->High = htole32((uint32_t)((data) >> 32)); ! (mps)->Low = htole32((uint32_t)((data) & 0xffffffff)); } static __inline uint64_t mps_to_u64(U64 *data) { ! return (((uint64_t)le32toh(data->High) << 32) | le32toh(data->Low)); } static __inline void *************** *** 686,692 **** MPI2_EVENT_NOTIFICATION_REPLY *event_reply); int mps_map_command(struct mps_softc *sc, struct mps_command *cm); ! int mps_wait_command(struct mps_softc *sc, struct mps_command *cm, int timeout); int mps_request_polled(struct mps_softc *sc, struct mps_command *cm); int mps_config_get_bios_pg3(struct mps_softc *sc, Mpi2ConfigReply_t --- 685,692 ---- MPI2_EVENT_NOTIFICATION_REPLY *event_reply); int mps_map_command(struct mps_softc *sc, struct mps_command *cm); ! int mps_wait_command(struct mps_softc *sc, struct mps_command *cm, int timeout, ! int sleep_flag); int mps_request_polled(struct mps_softc *sc, struct mps_command *cm); int mps_config_get_bios_pg3(struct mps_softc *sc, Mpi2ConfigReply_t *** src/sys/sys/param.h.orig --- src/sys/sys/param.h *************** *** 58,64 **** * in the range 5 to 9. */ #undef __FreeBSD_version ! #define __FreeBSD_version 901505 /* Master, propagated to newvers */ /* * __FreeBSD_kernel__ indicates that this system uses the kernel of FreeBSD, --- 58,64 ---- * in the range 5 to 9. */ #undef __FreeBSD_version ! #define __FreeBSD_version 901506 /* Master, propagated to newvers */ /* * __FreeBSD_kernel__ indicates that this system uses the kernel of FreeBSD, --k1lZvvs/B4yU6o8G--
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20130812190229.GA24478>