Index: sys/dev/mps/mpi/mpi2.h =================================================================== --- sys/dev/mps/mpi/mpi2.h (revision 253434) +++ sys/dev/mps/mpi/mpi2.h (working copy) @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2011, 2012 LSI Corp. + * Copyright (c) 2012 LSI Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without Index: sys/dev/mps/mpi/mpi2_cnfg.h =================================================================== --- sys/dev/mps/mpi/mpi2_cnfg.h (revision 253434) +++ sys/dev/mps/mpi/mpi2_cnfg.h (working copy) @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2011, 2012 LSI Corp. + * Copyright (c) 2012 LSI Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without Index: sys/dev/mps/mpi/mpi2_hbd.h =================================================================== --- sys/dev/mps/mpi/mpi2_hbd.h (revision 253434) +++ sys/dev/mps/mpi/mpi2_hbd.h (working copy) @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2011, 2012 LSI Corp. + * Copyright (c) 2012 LSI Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without Index: sys/dev/mps/mpi/mpi2_history.txt =================================================================== --- sys/dev/mps/mpi/mpi2_history.txt (revision 253434) +++ sys/dev/mps/mpi/mpi2_history.txt (working copy) @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2011, 2012 LSI Corp. + * Copyright (c) 2012 LSI Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without Index: sys/dev/mps/mpi/mpi2_init.h =================================================================== --- sys/dev/mps/mpi/mpi2_init.h (revision 253434) +++ sys/dev/mps/mpi/mpi2_init.h (working copy) @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2011, 2012 LSI Corp. + * Copyright (c) 2012 LSI Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without Index: sys/dev/mps/mpi/mpi2_ioc.h =================================================================== --- sys/dev/mps/mpi/mpi2_ioc.h (revision 253434) +++ sys/dev/mps/mpi/mpi2_ioc.h (working copy) @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2011, 2012 LSI Corp. + * Copyright (c) 2012 LSI Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without Index: sys/dev/mps/mpi/mpi2_ra.h =================================================================== --- sys/dev/mps/mpi/mpi2_ra.h (revision 253434) +++ sys/dev/mps/mpi/mpi2_ra.h (working copy) @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2011, 2012 LSI Corp. + * Copyright (c) 2012 LSI Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without Index: sys/dev/mps/mpi/mpi2_raid.h =================================================================== --- sys/dev/mps/mpi/mpi2_raid.h (revision 253434) +++ sys/dev/mps/mpi/mpi2_raid.h (working copy) @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2011, 2012 LSI Corp. + * Copyright (c) 2012 LSI Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without Index: sys/dev/mps/mpi/mpi2_sas.h =================================================================== --- sys/dev/mps/mpi/mpi2_sas.h (revision 253434) +++ sys/dev/mps/mpi/mpi2_sas.h (working copy) @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2011, 2012 LSI Corp. + * Copyright (c) 2012 LSI Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without Index: sys/dev/mps/mpi/mpi2_targ.h =================================================================== --- sys/dev/mps/mpi/mpi2_targ.h (revision 253434) +++ sys/dev/mps/mpi/mpi2_targ.h (working copy) @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2011, 2012 LSI Corp. + * Copyright (c) 2012 LSI Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without Index: sys/dev/mps/mpi/mpi2_tool.h =================================================================== --- sys/dev/mps/mpi/mpi2_tool.h (revision 253434) +++ sys/dev/mps/mpi/mpi2_tool.h (working copy) @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2011, 2012 LSI Corp. + * Copyright (c) 2012 LSI Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without Index: sys/dev/mps/mpi/mpi2_type.h =================================================================== --- sys/dev/mps/mpi/mpi2_type.h (revision 253434) +++ sys/dev/mps/mpi/mpi2_type.h (working copy) @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2011, 2012 LSI Corp. + * Copyright (c) 2012 LSI Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without Index: sys/dev/mps/mps.c =================================================================== --- sys/dev/mps/mps.c (revision 253434) +++ sys/dev/mps/mps.c (working copy) @@ -1,5 +1,7 @@ /*- * Copyright (c) 2009 Yahoo! Inc. + * All rights reserved. + * * Copyright (c) 2012 LSI Corp. * All rights reserved. * @@ -24,8 +26,6 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * LSI MPT-Fusion Host Adapter FreeBSD - * * $FreeBSD$ */ @@ -51,6 +51,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include @@ -61,6 +62,7 @@ __FBSDID("$FreeBSD$"); #include +#include #include #include @@ -73,13 +75,19 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include 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,6 +96,7 @@ static void mps_config_complete(struct mps_softc * 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,7 +157,8 @@ mps_diag_reset(struct mps_softc *sc,int sleep_flag 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); + msleep(&sc->msleep_fake_chan, &sc->mps_mtx, 0, + "mpsdiag", hz/10); else if (sleep_flag == CAN_SLEEP) pause("mpsdiag", hz/10); else @@ -172,7 +182,8 @@ mps_diag_reset(struct mps_softc *sc,int sleep_flag 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); + msleep(&sc->msleep_fake_chan, &sc->mps_mtx, 0, + "mpsdiag", hz/20); else if (sleep_flag == CAN_SLEEP) pause("mpsdiag", hz/20); else @@ -302,9 +313,357 @@ mps_transition_operational(struct mps_softc *sc) 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); +} + /* - * 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 @@ -316,7 +675,6 @@ int mps_reinit(struct mps_softc *sc) { int error; - uint32_t db; mps_printf(sc, "%s sc %p\n", __func__, sc); @@ -332,13 +690,15 @@ mps_reinit(struct mps_softc *sc) */ 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); + panic("%s hard reset failed with error %d\n", __func__, error); } /* Restore the PCI state, including the MSI-X registers */ @@ -347,49 +707,50 @@ mps_reinit(struct mps_softc *sc) /* 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", + /* + * 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); + } - /* 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. + /* + * Mapping structures will be re-allocated after getting IOC Page8, so + * free these structures here. */ - 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); + mps_mapping_exit(sc); - 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); - + /* + * 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); - mps_printf(sc, "%s restarting post %u free %u\n", __func__, - sc->replypostindex, sc->replyfreeindex); + /* + * 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 + /* + * 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, + 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; } @@ -634,48 +995,13 @@ mps_get_iocfacts(struct mps_softc *sc, MPI2_IOC_FA } 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; + struct timeval now; + uint64_t time_in_msec; mps_dprint(sc, MPS_TRACE, "%s\n", __func__); @@ -704,8 +1030,10 @@ mps_send_iocinit(struct mps_softc *sc) 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); + 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,7 +1447,7 @@ mps_setup_sysctl(struct mps_softc *sc) int mps_attach(struct mps_softc *sc) { - int i, error; + int error; mps_get_tunables(sc); @@ -1141,151 +1469,20 @@ mps_attach(struct mps_softc *sc) __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. + * 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 ((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); + 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); } - 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); @@ -1328,7 +1525,9 @@ mps_startup(void *arg) 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,8 +1610,7 @@ mps_detach_log(struct mps_softc *sc) int mps_free(struct mps_softc *sc) { - struct mps_command *cm; - int i, error; + int error; /* Turn off the watchdog */ mps_lock(sc); @@ -1438,62 +1636,15 @@ mps_free(struct mps_softc *sc) if (sc->facts != NULL) free(sc->facts, M_MPT2); - if (sc->pfacts != NULL) - free(sc->pfacts, 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->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); @@ -1914,7 +2065,7 @@ mps_reregister_events(struct mps_softc *sc) /* first, reregister events */ - for (i = 0; i < MPI2_EVENT_NOTIFY_EVENTMASK_WORDS; i++) + for (i = 0; i < MPI2_EVENT_NOTIFY_EVENTMASK_WORDS; i++) sc->event_mask[i] = -1; TAILQ_FOREACH(eh, &sc->event_list, eh_list) { @@ -1946,7 +2097,8 @@ mps_reregister_events(struct mps_softc *sc) error = mps_map_command(sc, cm); - mps_dprint(sc, MPS_TRACE, "%s finished with error %d\n", __func__, error); + mps_dprint(sc, MPS_TRACE, "%s finished with error %d\n", __func__, + error); return (error); } @@ -2300,26 +2452,50 @@ mps_map_command(struct mps_softc *sc, struct mps_c * be executed and enqueued automatically. Other errors come from msleep(). */ int -mps_wait_command(struct mps_softc *sc, struct mps_command *cm, int timeout) +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; - 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; + cm->cm_flags |= (MPS_CM_FLAGS_WAKEUP + MPS_CM_FLAGS_POLLED); error = mps_map_command(sc, cm); if ((error != 0) && (error != EINPROGRESS)) return (error); - error = msleep(cm, &sc->mps_mtx, 0, "mpswait", timeout*hz); + + // 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_no_sleeping != 0) + 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"); + mps_dprint(sc, MPS_FAULT, "Reinit %s\n", (rc == 0) ? "success" : + "failed"); error = ETIMEDOUT; } return (error); @@ -2419,7 +2595,7 @@ mps_read_config_page(struct mps_softc *sc, struct cm->cm_complete = mps_config_complete; return (mps_map_command(sc, cm)); } else { - error = mps_wait_command(sc, cm, 0); + error = mps_wait_command(sc, cm, 0, CAN_SLEEP); if (error) { mps_dprint(sc, MPS_FAULT, "Error %d reading config page\n", error); Index: sys/dev/mps/mps_config.c =================================================================== --- sys/dev/mps/mps_config.c (revision 253434) +++ sys/dev/mps/mps_config.c (working copy) @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2011, 2012 LSI Corp. + * Copyright (c) 2012 LSI Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -93,12 +93,15 @@ mps_config_get_ioc_pg8(struct mps_softc *sc, Mpi2C 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); + error = mps_wait_command(sc, cm, 60, CAN_SLEEP); 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", + /* + * 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,7 +110,10 @@ mps_config_get_ioc_pg8(struct mps_softc *sc, Mpi2C 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 */ + /* + * 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,12 +150,16 @@ mps_config_get_ioc_pg8(struct mps_softc *sc, Mpi2C goto out; } cm->cm_data = page; - error = mps_request_polled(sc, cm); + + error = mps_wait_command(sc, cm, 60, CAN_SLEEP); 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", + /* + * 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,7 +168,10 @@ mps_config_get_ioc_pg8(struct mps_softc *sc, Mpi2C 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 */ + /* + * 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,6 +224,11 @@ mps_config_get_man_pg10(struct mps_softc *sc, Mpi2 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,6 +280,11 @@ mps_config_get_man_pg10(struct mps_softc *sc, Mpi2 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)) { @@ -368,7 +391,7 @@ mps_wd_config_pages(struct mps_softc *sc) * Valid flag if Volume info fails. */ sc->WD_valid_config = FALSE; - if (sc->mps_flags & MPS_FLAGS_WD_AVAILABLE) { + if (sc->WD_available) { if (mps_config_get_man_pg10(sc, &mpi_reply)) { mps_dprint(sc, MPS_FAULT, "mps_config_get_man_pg10 failed! Using 0 (Hide " @@ -561,12 +584,15 @@ mps_config_get_dpm_pg0(struct mps_softc *sc, Mpi2C 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); + error = mps_wait_command(sc, cm, 60, CAN_SLEEP); 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", + /* + * 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,7 +601,10 @@ mps_config_get_dpm_pg0(struct mps_softc *sc, Mpi2C 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 */ + /* + * 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,12 +644,15 @@ mps_config_get_dpm_pg0(struct mps_softc *sc, Mpi2C goto out; } cm->cm_data = page; - error = mps_request_polled(sc, cm); + error = mps_wait_command(sc, cm, 60, CAN_SLEEP); 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", + /* + * 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,7 +661,10 @@ mps_config_get_dpm_pg0(struct mps_softc *sc, Mpi2C 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 */ + /* + * 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,12 +720,15 @@ int mps_config_set_dpm_pg0(struct mps_softc *sc, M 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); + error = mps_wait_command(sc, cm, 60, CAN_SLEEP); 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", + /* + * 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,7 +737,10 @@ int mps_config_set_dpm_pg0(struct mps_softc *sc, M 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 */ + /* + * 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,12 +782,15 @@ int mps_config_set_dpm_pg0(struct mps_softc *sc, M bcopy(config_page, page, MIN(cm->cm_length, (sizeof(Mpi2DriverMappingPage0_t)))); cm->cm_data = page; - error = mps_request_polled(sc, cm); + error = mps_wait_command(sc, cm, 60, CAN_SLEEP); 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", + /* + * 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,7 +799,10 @@ int mps_config_set_dpm_pg0(struct mps_softc *sc, M 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 */ + /* + * 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,12 +855,15 @@ mps_config_get_sas_device_pg0(struct mps_softc *sc 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); + error = mps_wait_command(sc, cm, 60, CAN_SLEEP); 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", + /* + * 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,7 +872,10 @@ mps_config_get_sas_device_pg0(struct mps_softc *sc 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 */ + /* + * 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,12 +915,15 @@ mps_config_get_sas_device_pg0(struct mps_softc *sc } cm->cm_data = page; - error = mps_request_polled(sc, cm); + error = mps_wait_command(sc, cm, 60, CAN_SLEEP); 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", + /* + * 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,7 +932,10 @@ mps_config_get_sas_device_pg0(struct mps_softc *sc 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 */ + /* + * 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,12 +987,15 @@ mps_config_get_bios_pg3(struct mps_softc *sc, Mpi2 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); + error = mps_wait_command(sc, cm, 60, CAN_SLEEP); 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", + /* + * 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,7 +1004,10 @@ mps_config_get_bios_pg3(struct mps_softc *sc, Mpi2 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 */ + /* + * 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,12 +1045,15 @@ mps_config_get_bios_pg3(struct mps_softc *sc, Mpi2 } cm->cm_data = page; - error = mps_request_polled(sc, cm); + error = mps_wait_command(sc, cm, 60, CAN_SLEEP); 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", + /* + * 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,7 +1062,10 @@ mps_config_get_bios_pg3(struct mps_softc *sc, Mpi2 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 */ + /* + * 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,6 +1117,11 @@ mps_config_get_raid_volume_pg0(struct mps_softc *s 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,6 +1175,10 @@ mps_config_get_raid_volume_pg0(struct mps_softc *s } 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,12 +1246,15 @@ mps_config_get_raid_volume_pg1(struct mps_softc *s 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); + error = mps_wait_command(sc, cm, 60, CAN_SLEEP); 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", + /* + * 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,7 +1263,10 @@ mps_config_get_raid_volume_pg1(struct mps_softc *s 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 */ + /* + * 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,12 +1305,15 @@ mps_config_get_raid_volume_pg1(struct mps_softc *s } cm->cm_data = page; - error = mps_request_polled(sc, cm); + error = mps_wait_command(sc, cm, 60, CAN_SLEEP); 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", + /* + * 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,7 +1322,10 @@ mps_config_get_raid_volume_pg1(struct mps_softc *s 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 */ + /* + * 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,6 +1403,11 @@ mps_config_get_raid_pd_pg0(struct mps_softc *sc, M 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,6 +1461,10 @@ mps_config_get_raid_pd_pg0(struct mps_softc *sc, M } 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)) { Index: sys/dev/mps/mps_ioctl.h =================================================================== --- sys/dev/mps/mps_ioctl.h (revision 253434) +++ sys/dev/mps/mps_ioctl.h (working copy) @@ -32,7 +32,7 @@ * $FreeBSD$ */ /*- - * Copyright (c) 2011, 2012 LSI Corp. + * Copyright (c) 2012 LSI Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without Index: sys/dev/mps/mps_mapping.c =================================================================== --- sys/dev/mps/mps_mapping.c (revision 253434) +++ sys/dev/mps/mps_mapping.c (working copy) @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2011, 2012 LSI Corp. + * Copyright (c) 2012 LSI Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -1216,12 +1216,12 @@ _mapping_add_new_device(struct mps_softc *sc, 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__, + 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,12 +1318,12 @@ _mapping_add_new_device(struct mps_softc *sc, 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__, + 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); } } Index: sys/dev/mps/mps_mapping.h =================================================================== --- sys/dev/mps/mps_mapping.h (revision 253434) +++ sys/dev/mps/mps_mapping.h (working copy) @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2011, 2012 LSI Corp. + * Copyright (c) 2012 LSI Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without Index: sys/dev/mps/mps_pci.c =================================================================== --- sys/dev/mps/mps_pci.c (revision 253434) +++ sys/dev/mps/mps_pci.c (working copy) @@ -140,7 +140,7 @@ struct mps_ident { { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2308_3, 0xffff, 0xffff, 0, "LSI SAS2308" }, { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SSS6200, - 0xffff, 0xffff, MPS_FLAGS_WD_AVAILABLE, "LSI SSS6200" }, + 0xffff, 0xffff, 0, "LSI SSS6200" }, { 0, 0, 0, 0, 0, NULL } }; Index: sys/dev/mps/mps_sas.c =================================================================== --- sys/dev/mps/mps_sas.c (revision 253434) +++ sys/dev/mps/mps_sas.c (working copy) @@ -1,8 +1,10 @@ /*- * Copyright (c) 2009 Yahoo! Inc. - * Copyright (c) 2011, 2012 LSI Corp. * All rights reserved. * + * Copyright (c) 2012 LSI Corp. + * All rights reserved. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -23,10 +25,6 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * LSI MPT-Fusion Host Adapter FreeBSD - * - * $FreeBSD$ */ #include @@ -61,7 +59,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include #include #include #include @@ -139,13 +136,8 @@ static int mpssas_send_reset(struct mps_softc *sc 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); static void mpssas_portenable_complete(struct mps_softc *sc, struct mps_command *cm); @@ -272,23 +264,19 @@ mpssas_rescan_target(struct mps_softc *sc, struct } if (xpt_create_path(&ccb->ccb_h.path, NULL, pathid, - targetid, CAM_LUN_WILDCARD) != CAM_REQ_CMP) { + targetid, CAM_LUN_WILDCARD) != CAM_REQ_CMP) { mps_dprint(sc, MPS_FAULT, "unable to create path for rescan\n"); xpt_free_ccb(ccb); return; } - if (targetid == CAM_TARGET_WILDCARD) - ccb->ccb_h.func_code = XPT_SCAN_BUS; - else - ccb->ccb_h.func_code = XPT_SCAN_TGT; - + /* XXX Hardwired to scan the bus for now */ + ccb->ccb_h.func_code = XPT_SCAN_BUS; mps_dprint(sc, MPS_TRACE, "%s targetid %u\n", __func__, targetid); mpssas_rescan(sassc, ccb); } -static void -mpssas_log_command(struct mps_command *cm, const char *fmt, ...) +static void mpssas_log_command(struct mps_command *cm, const char *fmt, ...) { struct sbuf sb; va_list ap; @@ -303,13 +291,11 @@ mpssas_rescan_target(struct mps_softc *sc, struct va_start(ap, fmt); if (cm->cm_ccb != NULL) { - xpt_path_string(cm->cm_ccb->csio.ccb_h.path, path_str, - sizeof(path_str)); + xpt_path_string(cm->cm_ccb->csio.ccb_h.path, path_str, sizeof(path_str)); sbuf_cat(&sb, path_str); if (cm->cm_ccb->ccb_h.func_code == XPT_SCSI_IO) { scsi_command_string(&cm->cm_ccb->csio, &sb); - sbuf_printf(&sb, "length %d ", - cm->cm_ccb->csio.dxfer_len); + sbuf_printf(&sb, "length %d ", cm->cm_ccb->csio.dxfer_len); } } else { @@ -449,13 +435,13 @@ mpssas_prepare_volume_remove(struct mpssas_softc * } /* - * The MPT2 firmware performs debounce on the link to avoid transient link - * errors and false removals. When it does decide that link has been lost - * and a device need to go away, it expects that the host will perform a - * target reset and then an op remove. The reset has the side-effect of - * aborting any outstanding requests for the device, which is required for - * the op-remove to succeed. It's not clear if the host should check for - * the device coming back alive after the reset. + * The MPT2 firmware performs debounce on the link to avoid transient link errors + * and false removals. When it does decide that link has been lost and a device + * need to go away, it expects that the host will perform a target reset and then + * an op remove. The reset has the side-effect of aborting any outstanding + * requests for the device, which is required for the op-remove to succeed. It's + * not clear if the host should check for the device coming back alive after the + * reset. */ void mpssas_prepare_remove(struct mpssas_softc *sassc, uint16_t handle) @@ -671,9 +657,6 @@ int 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__); @@ -702,7 +685,7 @@ mps_attach_sas(struct mps_softc *sc) } unit = device_get_unit(sc->mps_dev); - sassc->sim = cam_sim_alloc(mpssas_action, mpssas_poll, "mps", sassc, + sassc->sim = cam_sim_alloc(mpssas_action, mpssas_poll, "mpslsi", sassc, unit, &sc->mps_mtx, sc->num_reqs, sc->num_reqs, sassc->devq); if (sassc->sim == NULL) { mps_dprint(sc, MPS_FAULT, "Cannot allocate SIM\n"); @@ -758,14 +741,6 @@ mps_attach_sas(struct mps_softc *sc) 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); mpssas_register_events(sc); @@ -801,12 +776,6 @@ mps_detach_sas(struct mps_softc *sc) /* Make sure CAM doesn't wedge if we had to bail out early. */ 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); @@ -820,8 +789,7 @@ mps_detach_sas(struct mps_softc *sc) wakeup(&sassc->ccb_scanq); if (sassc->flags & MPSSAS_SCANTHREAD) { - msleep(&sassc->flags, &sc->mps_mtx, PRIBIO, - "mps_shutdown", 30 * hz); + msleep(&sassc->flags, &sc->mps_mtx, PRIBIO, "mps_shutdown", 30 * hz); } } mps_unlock(sc); @@ -930,9 +898,6 @@ mpssas_action(struct cam_sim *sim, union ccb *ccb) cpi->protocol = PROTO_SCSI; cpi->protocol_version = SCSI_REV_SPC; #if __FreeBSD_version >= 800001 - /* - * XXX KDM where does this number come from? - */ cpi->maxio = 256 * 1024; #endif cpi->ccb_h.status = CAM_REQ_CMP; @@ -951,7 +916,7 @@ mpssas_action(struct cam_sim *sim, union ccb *ccb) targ = &sassc->targets[cts->ccb_h.target_id]; if (targ->handle == 0x0) { - cts->ccb_h.status = CAM_SEL_TIMEOUT; + cts->ccb_h.status = CAM_TID_INVALID; break; } @@ -992,8 +957,7 @@ mpssas_action(struct cam_sim *sim, union ccb *ccb) case XPT_RESET_BUS: case XPT_ABORT: case XPT_TERM_IO: - mps_printf(sassc->sc, "mpssas_action faking success for " - "abort or reset\n"); + mps_printf(sassc->sc, "mpssas_action faking success for abort or reset\n"); ccb->ccb_h.status = CAM_REQ_CMP; break; case XPT_SCSI_IO: @@ -1024,8 +988,7 @@ mpssas_announce_reset(struct mps_softc *sc, uint32 if (xpt_create_path(&path, NULL, path_id, target_id, lun_id) != CAM_REQ_CMP) { - mps_printf(sc, "unable to create path for reset " - "notification\n"); + mps_printf(sc, "unable to create path for reset notification\n"); return; } @@ -1072,9 +1035,8 @@ mpssas_complete_all_commands(struct mps_softc *sc) if ((completed == 0) && (cm->cm_state != MPS_CM_STATE_FREE)) { /* this should never happen, but if it does, log */ mpssas_log_command(cm, - "cm %p state %x flags 0x%x ccb %p during diag " - "reset\n", cm, cm->cm_state, cm->cm_flags, - cm->cm_ccb); + "cm %p state %x flags 0x%x ccb %p during diag reset\n", + cm, cm->cm_state, cm->cm_flags, cm->cm_ccb); } } } @@ -1580,22 +1542,34 @@ mpssas_action_scsiio(struct mpssas_softc *sassc, u 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); + 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); - csio->ccb_h.status = CAM_SEL_TIMEOUT; + csio->ccb_h.status = CAM_TID_INVALID; xpt_done(ccb); 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); + 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. @@ -1791,6 +1765,7 @@ mpssas_action_scsiio(struct mpssas_softc *sassc, u 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,14 +1944,13 @@ mps_sc_failed_io_info(struct mps_softc *sc, struct 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); + 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); + "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) { @@ -2001,6 +1975,7 @@ mpssas_scsiio_complete(struct mps_softc *sc, struc struct mpssas_softc *sassc; struct scsi_vpd_supported_page_list *vpd_list = NULL; u8 *TLR_bits, TLR_on; + u_int sense_len; int dir = 0, i; u16 alloc_len; @@ -2033,6 +2008,7 @@ mpssas_scsiio_complete(struct mps_softc *sc, struc 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,7 +2084,7 @@ mpssas_scsiio_complete(struct mps_softc *sc, struc ccb->ccb_h.status |= CAM_RELEASE_SIMQ; sassc->flags &= ~MPSSAS_QUEUE_FROZEN; mps_dprint(sc, MPS_INFO, - "Unfreezing SIM queue\n"); + "Unfreezing SIM queue\n"); } } @@ -2209,21 +2185,11 @@ mpssas_scsiio_complete(struct mps_softc *sc, struc ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR; if (rep->SCSIState & MPI2_SCSI_STATE_AUTOSENSE_VALID) { - int sense_len, returned_sense_len; - - returned_sense_len = min(le32toh(rep->SenseCount), + sense_len = MIN(le32toh(rep->SenseCount), sizeof(struct scsi_sense_data)); - if (returned_sense_len < ccb->csio.sense_len) - ccb->csio.sense_resid = ccb->csio.sense_len - - returned_sense_len; - else - ccb->csio.sense_resid = 0; - - sense_len = min(returned_sense_len, - ccb->csio.sense_len - ccb->csio.sense_resid); - bzero(&ccb->csio.sense_data, - sizeof(ccb->csio.sense_data)); - bcopy(cm->cm_sense, &ccb->csio.sense_data, sense_len); + if (sense_len < le32toh(rep->SenseCount)) + csio->sense_resid = le32toh(rep->SenseCount) - sense_len; + bcopy(cm->cm_sense, &csio->sense_data, sense_len); ccb->ccb_h.status |= CAM_AUTOSNS_VALID; } @@ -2335,7 +2301,7 @@ mpssas_scsiio_complete(struct mps_softc *sc, struc ccb->ccb_h.status |= CAM_RELEASE_SIMQ; sassc->flags &= ~MPSSAS_QUEUE_FROZEN; mps_dprint(sc, MPS_INFO, "Command completed, " - "unfreezing SIM queue\n"); + "unfreezing SIM queue\n"); } if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) { @@ -2651,7 +2617,8 @@ mpssas_smpio_complete(struct mps_softc *sc, struct sasaddr = le32toh(req->SASAddress.Low); sasaddr |= ((uint64_t)(le32toh(req->SASAddress.High))) << 32; - if ((le16toh(rpl->IOCStatus) & MPI2_IOCSTATUS_MASK) != MPI2_IOCSTATUS_SUCCESS || + 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,7 +2741,7 @@ mpssas_send_smpcmd(struct mpssas_softc *sassc, uni 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); + "address %#jx\n", __func__, (uintmax_t)sasaddr); mpi_init_sge(cm, req, &req->SGL); @@ -2992,7 +2959,8 @@ mpssas_action_resetdev(struct mpssas_softc *sassc, sc = sassc->sc; tm = mps_alloc_command(sc); if (tm == NULL) { - mps_printf(sc, "comand alloc failure in mpssas_action_resetdev\n"); + mps_printf(sc, "comand alloc failure in " + "mpssas_action_resetdev\n"); ccb->ccb_h.status = CAM_RESRC_UNAVAIL; xpt_done(ccb); return; @@ -3098,14 +3066,11 @@ mpssas_rescan_done(struct cam_periph *periph, unio 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 */ @@ -3152,17 +3117,6 @@ next_work: 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) { @@ -3186,102 +3140,18 @@ mpssas_rescan(struct mpssas_softc *sassc, union cc wakeup(&sassc->ccb_scanq); } -#if __FreeBSD_version >= 1000006 +/* + * 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_async(void *callback_arg, uint32_t code, struct cam_path *path, - void *arg) -{ - struct mps_softc *sc; - - sc = (struct mps_softc *)callback_arg; - - switch (code) { - case AC_ADVINFO_CHANGED: { - struct mpssas_target *target; - struct mpssas_softc *sassc; - struct scsi_read_capacity_data_long rcap_buf; - struct ccb_dev_advinfo cdai; - struct mpssas_lun *lun; - lun_id_t lunid; - int found_lun; - uintptr_t buftype; - - buftype = (uintptr_t)arg; - - found_lun = 0; - sassc = sc->sassc; - - /* - * We're only interested in read capacity data changes. - */ - if (buftype != CDAI_TYPE_RCAPLONG) - 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)]; - if (target->handle == 0) - break; - - lunid = xpt_path_lun_id(path); - - SLIST_FOREACH(lun, &target->luns, lun_link) { - if (lun->lun_id == lunid) { - found_lun = 1; - break; - } - } - - if (found_lun == 0) { - 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"); - break; - } - lun->lun_id = lunid; - SLIST_INSERT_HEAD(&target->luns, lun, lun_link); - } - - bzero(&rcap_buf, sizeof(rcap_buf)); - xpt_setup_ccb(&cdai.ccb_h, path, CAM_PRIORITY_NORMAL); - cdai.ccb_h.func_code = XPT_DEV_ADVINFO; - cdai.ccb_h.flags = CAM_DIR_IN; - cdai.buftype = CDAI_TYPE_RCAPLONG; - cdai.flags = 0; - cdai.bufsiz = sizeof(rcap_buf); - cdai.buf = (uint8_t *)&rcap_buf; - xpt_action((union ccb *)&cdai); - if ((cdai.ccb_h.status & CAM_DEV_QFRZN) != 0) - cam_release_devq(cdai.ccb_h.path, - 0, 0, 0, FALSE); - - if (((cdai.ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP) - && (rcap_buf.prot & SRC16_PROT_EN)) { - lun->eedp_formatted = TRUE; - lun->eedp_block_size = scsi_4btoul(rcap_buf.length); - } else { - lun->eedp_formatted = FALSE; - lun->eedp_block_size = 0; - } - break; - } - default: - break; - } -} -#else /* __FreeBSD_version >= 1000006 */ - -static void mpssas_check_eedp(struct mpssas_softc *sassc) { struct mps_softc *sc = sassc->sc; @@ -3292,14 +3162,33 @@ mpssas_check_eedp(struct mpssas_softc *sassc) 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; + struct ccb_dev_match cdm; + struct dev_match_result LUN_match; + struct dev_match_pattern LUN_pattern; char path_str[64]; + mps_dprint(sc, MPS_TRACE, "%s\n", __func__); + /* + * Set the initial Device Match values. These values will not change + * for the entire search. + */ + cdm.ccb_h.func_code = XPT_DEV_MATCH; + cdm.matches = &LUN_match; + cdm.match_buf_len = sizeof(struct dev_match_result); + LUN_pattern.type = DEV_MATCH_DEVICE; + LUN_pattern.pattern.device_pattern.path_id = pathid; + LUN_pattern.pattern.device_pattern.flags = DEV_MATCH_PATH | + DEV_MATCH_TARGET; + cdm.patterns = &LUN_pattern; + cdm.pattern_buf_len = sizeof(struct dev_match_pattern); + cdm.num_patterns = 1; + + /* * 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. */ @@ -3309,7 +3198,13 @@ mpssas_check_eedp(struct mpssas_softc *sassc) continue; } - lunid = 0; + /* + * Only one 'matches' element is allocated to get one match at + * a time for the given path and target. All LUNs for the path + * and target will be matched. + */ + cdm.pos.position_type = CAM_DEV_POS_NONE; + LUN_pattern.pattern.device_pattern.target_id = targetid; do { ccb = xpt_alloc_ccb_nowait(); if (ccb == NULL) { @@ -3317,25 +3212,29 @@ mpssas_check_eedp(struct mpssas_softc *sassc) "for EEDP support.\n"); return; } - if (xpt_create_path(&ccb->ccb_h.path, NULL, - pathid, targetid, lunid) != CAM_REQ_CMP) { + pathid, targetid, CAM_LUN_WILDCARD) != + CAM_REQ_CMP) { mps_dprint(sc, MPS_FAULT, "Unable to create " - "path for EEDP support\n"); + "path for EEDP support.\n"); xpt_free_ccb(ccb); return; } + xpt_setup_ccb(&cdm.ccb_h, ccb->ccb_h.path, + CAM_PRIORITY_NORMAL); + xpt_action((union ccb *)&cdm); /* - * If a periph is returned, the LUN exists. Create an - * entry in the target's LUN list. + * If a LUN was found, create an entry in the target's + * LUN list. If LUN is already in list, don't create a + * new one. Make sure that only one LUN was matched. + * If more than one, that's undefined due to the way + * the search is set up. Don't add CAM_LUN_WILDCARD + * LUN IDs to the target's 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. - */ + lunid = cdm.matches[0].result.device_result.target_lun; + if ((cdm.num_matches == 1) && (lunid != + CAM_LUN_WILDCARD)) { found_lun = FALSE; SLIST_FOREACH(lun, &target->luns, lun_link) { if (lun->lun_id == lunid) { @@ -3344,6 +3243,9 @@ mpssas_check_eedp(struct mpssas_softc *sassc) } } if (!found_lun) { + mps_dprint(sc, MPS_INFO, "Adding LUN " + "%d to target ID %d's lun list\n", + lunid, targetid); lun = malloc(sizeof(struct mpssas_lun), M_MPT2, M_NOWAIT | M_ZERO); if (lun == NULL) { @@ -3358,36 +3260,55 @@ mpssas_check_eedp(struct mpssas_softc *sassc) SLIST_INSERT_HEAD(&target->luns, lun, lun_link); } - lunid++; - /* Before Issuing READ CAPACITY 16, - * check Device type. + + /* + * Before Issuing READ CAPACITY 16, check Device + * type. Create a new path with the matched + * LUN. */ - xpt_setup_ccb(&cgd.ccb_h, ccb->ccb_h.path, - CAM_PRIORITY_NORMAL); + xpt_free_path(ccb->ccb_h.path); + xpt_free_ccb(ccb); + ccb = xpt_alloc_ccb_nowait(); + if (ccb == NULL) { + mps_dprint(sc, MPS_FAULT, "Unable to " + "alloc LUN CCB for EEDP " + "support.\n"); + return; + } + if (xpt_create_path(&ccb->ccb_h.path, + NULL, pathid, targetid, lunid) != + CAM_REQ_CMP) { + mps_dprint(sc, MPS_FAULT, "Unable to " + "create LUN path for EEDP " + "support.\n"); + xpt_free_ccb(ccb); + return; + } + 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 + * 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)); - xpt_path_string(ccb->ccb_h.path, path_str, - sizeof(path_str)); - - if ((cgd.inq_data.spc3_flags & - SPC3_SID_PROTECT) == 0) { + 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 ); + 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. @@ -3394,12 +3315,13 @@ mpssas_check_eedp(struct mpssas_softc *sassc) * 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); + 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"); + 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; @@ -3433,9 +3355,7 @@ mpssas_check_eedp(struct mpssas_softc *sassc) 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.target_lun = lunid; ccb->ccb_h.ppriv_ptr1 = sassc; xpt_action(ccb); } else { @@ -3442,11 +3362,10 @@ mpssas_check_eedp(struct mpssas_softc *sassc) xpt_free_path(ccb->ccb_h.path); xpt_free_ccb(ccb); } - } while (found_periph); + } while (cdm.status == CAM_DEV_MATCH_MORE); } } - static void mpssas_read_cap_done(struct cam_periph *periph, union ccb *done_ccb) { @@ -3453,7 +3372,7 @@ mpssas_read_cap_done(struct cam_periph *periph, un struct mpssas_softc *sassc; struct mpssas_target *target; struct mpssas_lun *lun; - struct scsi_read_capacity_eedp *rcap_buf; + uint8_t *rcap_buf = done_ccb->csio.data_ptr; if (done_ccb == NULL) return; @@ -3472,8 +3391,6 @@ mpssas_read_cap_done(struct cam_periph *periph, un /*count*/ 1, /*run_queue*/TRUE); } - rcap_buf = (struct scsi_read_capacity_eedp *)done_ccb->csio.data_ptr; - /* * Get the LUN ID for the path and look it up in the LUN list for the * target. @@ -3481,28 +3398,32 @@ mpssas_read_cap_done(struct cam_periph *periph, un sassc = (struct mpssas_softc *)done_ccb->ccb_h.ppriv_ptr1; target = &sassc->targets[done_ccb->ccb_h.target_id]; SLIST_FOREACH(lun, &target->luns, lun_link) { - if (lun->lun_id != done_ccb->ccb_h.target_lun) - continue; + if (lun->lun_id == done_ccb->ccb_h.target_lun) { + /* + * Got the LUN in the target's LUN list. Fill it in + * with EEDP info. If the READ CAP 16 command had some + * SCSI error (common if command is not supported), mark + * the lun as not supporting EEDP and set the block size + * to 0. + */ + if (done_ccb->csio.scsi_status != SCSI_STATUS_OK) { + lun->eedp_formatted = FALSE; + lun->eedp_block_size = 0; + break; + } - /* - * Got the LUN in the target's LUN list. Fill it in - * with EEDP info. If the READ CAP 16 command had some - * SCSI error (common if command is not supported), mark - * the lun as not supporting EEDP and set the block size - * to 0. - */ - if (((done_ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) - || (done_ccb->csio.scsi_status != SCSI_STATUS_OK)) { - lun->eedp_formatted = FALSE; - lun->eedp_block_size = 0; + if (rcap_buf[12] & 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 = (uint32_t)( + (rcap_buf[8] << 24) + (rcap_buf[9] << 16) + + (rcap_buf[10] << 8) + rcap_buf[11]); + } break; } - - if (rcap_buf->protect & 0x01) { - lun->eedp_formatted = TRUE; - lun->eedp_block_size = scsi_4btoul(rcap_buf->length); - } - break; } // Finished with this CCB and path. @@ -3510,7 +3431,6 @@ mpssas_read_cap_done(struct cam_periph *periph, un xpt_free_path(done_ccb->ccb_h.path); xpt_free_ccb(done_ccb); } -#endif /* __FreeBSD_version >= 1000006 */ int mpssas_startup(struct mps_softc *sc) Index: sys/dev/mps/mps_sas.h =================================================================== --- sys/dev/mps/mps_sas.h (revision 253434) +++ sys/dev/mps/mps_sas.h (working copy) @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2011, 2012 LSI Corp. + * Copyright (c) 2012 LSI Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without Index: sys/dev/mps/mps_sas_lsi.c =================================================================== --- sys/dev/mps/mps_sas_lsi.c (revision 253434) +++ sys/dev/mps/mps_sas_lsi.c (working copy) @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2011, 2012 LSI Corp. + * Copyright (c) 2012 LSI Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -818,12 +818,15 @@ mpssas_get_sata_identify(struct mps_softc *sc, u16 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); + error = mps_wait_command(sc, cm, 60, CAN_SLEEP); 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", + /* + * 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,7 +958,7 @@ mpssas_ir_shutdown(struct mps_softc *sc) 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_wait_command(sc, cm, 5, CAN_SLEEP); mps_unlock(sc); /* Index: sys/dev/mps/mps_table.h =================================================================== --- sys/dev/mps/mps_table.h (revision 253434) +++ sys/dev/mps/mps_table.h (working copy) @@ -22,8 +22,6 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * $FreeBSD$ */ #ifndef _MPS_TABLE_H Index: sys/dev/mps/mps_user.c =================================================================== --- sys/dev/mps/mps_user.c (revision 253434) +++ sys/dev/mps/mps_user.c (working copy) @@ -30,7 +30,7 @@ * LSI MPT-Fusion Host Adapter FreeBSD userland interface */ /*- - * Copyright (c) 2011, 2012 LSI Corp. + * Copyright (c) 2012 LSI Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -669,7 +669,7 @@ mps_user_command(struct mps_softc *sc, struct mps_ cm = mps_alloc_command(sc); if (cm == NULL) { - mps_printf(sc, "mps_user_command: no mps requests\n"); + mps_printf(sc, "%s: no mps requests\n", __func__); err = ENOMEM; goto Ret; } @@ -677,8 +677,8 @@ mps_user_command(struct mps_softc *sc, struct mps_ 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 ); + 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; @@ -688,9 +688,18 @@ mps_user_command(struct mps_softc *sc, struct mps_ if (err != 0) goto RetFreeUnlocked; - mps_dprint(sc, MPS_INFO, "mps_user_command: Function %02X " - "MsgFlags %02X\n", hdr->Function, hdr->MsgFlags ); + 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 == EINVAL) { + mps_printf(sc, "%s: unsupported parameter or unsupported " + "function in request (function = 0x%X)\n", __func__, + hdr->Function); + } + if (err != 0) + goto RetFreeUnlocked; + if (cmd->len > 0) { buf = malloc(cmd->len, M_MPSUSER, M_WAITOK|M_ZERO); if(!buf) { @@ -708,15 +717,8 @@ mps_user_command(struct mps_softc *sc, struct mps_ 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 != 0) { - mps_printf(sc, "mps_user_command: unsupported function 0x%X\n", - hdr->Function ); - goto RetFreeUnlocked; - } - mps_lock(sc); - err = mps_wait_command(sc, cm, 60); + err = mps_wait_command(sc, cm, 30, CAN_SLEEP); if (err) { mps_printf(sc, "%s: invalid request: error %d\n", @@ -731,10 +733,8 @@ mps_user_command(struct mps_softc *sc, struct mps_ sz = 0; 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; + mps_printf(sc, "%s: user reply buffer (%d) smaller than " + "returned buffer (%d)\n", __func__, cmd->rpl_len, sz); sz = cmd->rpl_len; } @@ -742,7 +742,7 @@ mps_user_command(struct mps_softc *sc, struct mps_ 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 ); + mps_dprint(sc, MPS_INFO, "%s: reply size %d\n", __func__, sz); RetFreeUnlocked: mps_lock(sc); @@ -849,7 +849,7 @@ mps_user_pass_thru(struct mps_softc *sc, mps_pass_ cm->cm_complete = NULL; cm->cm_complete_data = NULL; - err = mps_wait_command(sc, cm, 30); + err = mps_wait_command(sc, cm, 30, CAN_SLEEP); if (err != 0) { err = EIO; @@ -864,15 +864,14 @@ mps_user_pass_thru(struct mps_softc *sc, mps_pass_ 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); + 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,7 +985,7 @@ mps_user_pass_thru(struct mps_softc *sc, mps_pass_ mps_lock(sc); - err = mps_wait_command(sc, cm, 30); + err = mps_wait_command(sc, cm, 30, CAN_SLEEP); if (err) { mps_printf(sc, "%s: invalid request: error %d\n", __func__, @@ -1025,15 +1024,13 @@ mps_user_pass_thru(struct mps_softc *sc, mps_pass_ 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); + 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)) { @@ -1089,7 +1086,7 @@ mps_user_get_adapter_data(struct mps_softc *sc, mp * General device info. */ data->AdapterType = MPSIOCTL_ADAPTER_TYPE_SAS2; - if (sc->mps_flags & MPS_FLAGS_WD_AVAILABLE) + if (sc->WD_available) data->AdapterType = MPSIOCTL_ADAPTER_TYPE_SAS2_SSS6200; data->PCIDeviceHwId = pci_get_device(sc->mps_dev); data->PCIDeviceHwRev = pci_read_config(sc->mps_dev, PCIR_REVID, 1); @@ -1203,7 +1200,7 @@ mps_post_fw_diag_buffer(struct mps_softc *sc, /* * Send command synchronously. */ - status = mps_wait_command(sc, cm, 30); + status = mps_wait_command(sc, cm, 30, CAN_SLEEP); if (status) { mps_printf(sc, "%s: invalid request: error %d\n", __func__, status); @@ -1252,8 +1249,8 @@ mps_release_fw_diag_buffer(struct mps_softc *sc, */ *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__); + mps_dprint(sc, MPS_INFO, "%s: This buffer type is not " + "supported by the IOC", __func__); return (MPS_DIAG_FAILURE); } @@ -1287,7 +1284,7 @@ mps_release_fw_diag_buffer(struct mps_softc *sc, /* * Send command synchronously. */ - status = mps_wait_command(sc, cm, 30); + status = mps_wait_command(sc, cm, 30, CAN_SLEEP); if (status) { mps_printf(sc, "%s: invalid request: error %d\n", __func__, status); Index: sys/dev/mps/mpsvar.h =================================================================== --- sys/dev/mps/mpsvar.h (revision 253434) +++ sys/dev/mps/mpsvar.h (working copy) @@ -1,8 +1,10 @@ /*- * Copyright (c) 2009 Yahoo! Inc. - * Copyright (c) 2011, 2012 LSI Corp. * All rights reserved. * + * Copyright (c) 2012 LSI Corp. + * All rights reserved. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -24,8 +26,6 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * LSI MPT-Fusion Host Adapter FreeBSD - * * $FreeBSD$ */ @@ -32,7 +32,7 @@ #ifndef _MPSVAR_H #define _MPSVAR_H -#define MPS_DRIVER_VERSION "14.00.00.02-fbsd" +#define MPS_DRIVER_VERSION "16.00.00.00-fbsd" #define MPS_DB_MAX_WAIT 2500 @@ -266,7 +266,6 @@ struct mps_softc { #define MPS_FLAGS_SHUTDOWN (1 << 3) #define MPS_FLAGS_DIAGRESET (1 << 4) #define MPS_FLAGS_ATTACH_DONE (1 << 5) -#define MPS_FLAGS_WD_AVAILABLE (1 << 6) u_int mps_debug; u_int disable_msix; u_int disable_msi; @@ -304,7 +303,6 @@ struct mps_softc { 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 */ @@ -402,7 +400,7 @@ struct mps_softc { uint8_t msleep_fake_chan; /* WD controller */ - uint8_t WD_available; + uint8_t WD_available; uint8_t WD_valid_config; uint8_t WD_hide_expose; @@ -686,7 +684,8 @@ void mpssas_record_event(struct mps_softc *sc, 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_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