Print this page
Fix identifying 2308 cards
Add support for more than 8 MSI-X interrupts.
Tidy up interrupt assignement and card ID messages.
Added code to support using MSI-X interrupts across multiple
reply queues. Not tested with anything other than 3008 yet.
Use MSI-X interrupts, just one for now.
Pre-allocate array for request sense buffers, similar to command frames.
No more messing about with scsi_alloc_consistent_buf().
Initial modifications using the code changes present between
the LSI source code for FreeBSD drivers. Specifically the changes
between from mpslsi-source-17.00.00.00 -> mpslsi-source-03.00.00.00.
This mainly involves using a different scatter/gather element in
frame setup.
Changes to enable driver to compile.
Header paths, object lists, etc.

*** 20,29 **** --- 20,30 ---- */ /* * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. + * Copyright (c) 2014, Tegile Systems Inc. All rights reserved. */ /* * Copyright (c) 2000 to 2009, LSI Corporation. * All rights reserved.
*** 65,85 **** */ #include <sys/note.h> #include <sys/scsi/scsi.h> #pragma pack(1) ! #include <sys/scsi/adapters/mpt_sas/mpi/mpi2_type.h> ! #include <sys/scsi/adapters/mpt_sas/mpi/mpi2.h> ! #include <sys/scsi/adapters/mpt_sas/mpi/mpi2_cnfg.h> ! #include <sys/scsi/adapters/mpt_sas/mpi/mpi2_init.h> ! #include <sys/scsi/adapters/mpt_sas/mpi/mpi2_ioc.h> ! #include <sys/scsi/adapters/mpt_sas/mpi/mpi2_tool.h> #pragma pack() /* * private header files. */ ! #include <sys/scsi/adapters/mpt_sas/mptsas_var.h> static int mptsas_ioc_do_get_facts(mptsas_t *mpt, caddr_t memp, int var, ddi_acc_handle_t accessp); static int mptsas_ioc_do_get_facts_reply(mptsas_t *mpt, caddr_t memp, int var, ddi_acc_handle_t accessp); --- 66,86 ---- */ #include <sys/note.h> #include <sys/scsi/scsi.h> #pragma pack(1) ! #include <sys/scsi/adapters/mpt_sas3/mpi/mpi2_type.h> ! #include <sys/scsi/adapters/mpt_sas3/mpi/mpi2.h> ! #include <sys/scsi/adapters/mpt_sas3/mpi/mpi2_cnfg.h> ! #include <sys/scsi/adapters/mpt_sas3/mpi/mpi2_init.h> ! #include <sys/scsi/adapters/mpt_sas3/mpi/mpi2_ioc.h> ! #include <sys/scsi/adapters/mpt_sas3/mpi/mpi2_tool.h> #pragma pack() /* * private header files. */ ! #include <sys/scsi/adapters/mpt_sas3/mptsas3_var.h> static int mptsas_ioc_do_get_facts(mptsas_t *mpt, caddr_t memp, int var, ddi_acc_handle_t accessp); static int mptsas_ioc_do_get_facts_reply(mptsas_t *mpt, caddr_t memp, int var, ddi_acc_handle_t accessp);
*** 99,114 **** ddi_acc_handle_t accessp); static int mptsas_do_ioc_init_reply(mptsas_t *mpt, caddr_t memp, int var, ddi_acc_handle_t accessp); static const char * ! mptsas_product_type_string(mptsas_t *mpt) { ! switch (mpt->m_productid & MPI2_FW_HEADER_PID_PROD_MASK) { ! ! case MPI2_FW_HEADER_PID_PROD_A: ! return ("A"); default: return ("?"); } } --- 100,150 ---- ddi_acc_handle_t accessp); static int mptsas_do_ioc_init_reply(mptsas_t *mpt, caddr_t memp, int var, ddi_acc_handle_t accessp); static const char * ! mptsas_devid_type_string(mptsas_t *mpt) { ! switch (mpt->m_devid) { ! case MPI2_MFGPAGE_DEVID_SAS2008: ! return ("SAS2008"); ! case MPI2_MFGPAGE_DEVID_SAS2004: ! return ("SAS2004"); ! case MPI2_MFGPAGE_DEVID_SAS2108_1: ! case MPI2_MFGPAGE_DEVID_SAS2108_2: ! case MPI2_MFGPAGE_DEVID_SAS2108_3: ! return ("SAS2108"); ! case MPI2_MFGPAGE_DEVID_SAS2116_1: ! case MPI2_MFGPAGE_DEVID_SAS2116_2: ! return ("SAS2116"); ! case MPI2_MFGPAGE_DEVID_SAS2208_1: ! case MPI2_MFGPAGE_DEVID_SAS2208_2: ! case MPI2_MFGPAGE_DEVID_SAS2208_3: ! case MPI2_MFGPAGE_DEVID_SAS2208_4: ! case MPI2_MFGPAGE_DEVID_SAS2208_5: ! case MPI2_MFGPAGE_DEVID_SAS2208_6: ! #if 0 ! /* These are the same as the next 2?? */ ! case MPI2_MFGPAGE_DEVID_SAS2208_7: ! case MPI2_MFGPAGE_DEVID_SAS2208_8: ! #endif ! return ("SAS2208"); ! case MPI2_MFGPAGE_DEVID_SAS2308_1: ! case MPI2_MFGPAGE_DEVID_SAS2308_2: ! case MPI2_MFGPAGE_DEVID_SAS2308_3: ! return ("SAS2308"); ! case MPI25_MFGPAGE_DEVID_SAS3004: ! return ("SAS3004"); ! case MPI25_MFGPAGE_DEVID_SAS3008: ! return ("SAS3008"); ! case MPI25_MFGPAGE_DEVID_SAS3108_1: ! case MPI25_MFGPAGE_DEVID_SAS3108_2: ! case MPI25_MFGPAGE_DEVID_SAS3108_3: ! case MPI25_MFGPAGE_DEVID_SAS3108_4: ! case MPI25_MFGPAGE_DEVID_SAS3108_5: ! case MPI25_MFGPAGE_DEVID_SAS3108_6: ! return ("SAS3108"); default: return ("?"); } }
*** 174,183 **** --- 210,220 ---- uint16_t numReplyFrames; uint16_t queueSize, queueDiff; int simple_sge_main; int simple_sge_next; uint32_t capabilities; + uint16_t msgversion; bzero(memp, sizeof (*factsreply)); factsreply = (void *)memp; numbytes = sizeof (*factsreply);
*** 205,216 **** (void) sprintf(buf, "%u.%u.%u.%u", ddi_get8(accessp, &factsreply->FWVersion.Struct.Major), ddi_get8(accessp, &factsreply->FWVersion.Struct.Minor), ddi_get8(accessp, &factsreply->FWVersion.Struct.Unit), ddi_get8(accessp, &factsreply->FWVersion.Struct.Dev)); ! mptsas_log(mpt, CE_NOTE, "?mpt%d Firmware version v%s (%s)\n", ! mpt->m_instance, buf, mptsas_product_type_string(mpt)); (void) ddi_prop_update_string(DDI_DEV_T_NONE, mpt->m_dip, "firmware-version", buf); /* * Set up request info. --- 242,253 ---- (void) sprintf(buf, "%u.%u.%u.%u", ddi_get8(accessp, &factsreply->FWVersion.Struct.Major), ddi_get8(accessp, &factsreply->FWVersion.Struct.Minor), ddi_get8(accessp, &factsreply->FWVersion.Struct.Unit), ddi_get8(accessp, &factsreply->FWVersion.Struct.Dev)); ! mptsas_log(mpt, CE_NOTE, "?MPT Firmware version v%s (%s)\n", ! buf, mptsas_devid_type_string(mpt)); (void) ddi_prop_update_string(DDI_DEV_T_NONE, mpt->m_dip, "firmware-version", buf); /* * Set up request info.
*** 243,252 **** --- 280,292 ---- * be a multiple of 16. This size can be no larger than * MaxReplyDescriptorPostQueueDepth from IOCFacts. If the * calculated queue size is larger than allowed, subtract a * multiple of 16 from m_max_requests, m_max_replies, and * m_reply_free_depth. + * + * There is no indication in the spec that you can reduce the + * queue size if you have many. */ queueSize = mpt->m_max_requests + numReplyFrames + 1; if (queueSize % 16) { queueSize += 16 - (queueSize % 16); }
*** 269,285 **** */ mpt->m_max_chain_depth = ddi_get8(accessp, &factsreply->MaxChainDepth); mpt->m_ioc_capabilities = ddi_get32(accessp, &factsreply->IOCCapabilities); /* * Calculate max frames per request based on DMA S/G length. */ simple_sge_main = MPTSAS_MAX_FRAME_SGES64(mpt) - 1; simple_sge_next = mpt->m_req_frame_size / ! sizeof (MPI2_SGE_SIMPLE64) - 1; mpt->m_max_request_frames = (MPTSAS_MAX_DMA_SEGS - simple_sge_main) / simple_sge_next + 1; if (((MPTSAS_MAX_DMA_SEGS - simple_sge_main) % simple_sge_next) > 1) { --- 309,343 ---- */ mpt->m_max_chain_depth = ddi_get8(accessp, &factsreply->MaxChainDepth); mpt->m_ioc_capabilities = ddi_get32(accessp, &factsreply->IOCCapabilities); + if (mpt->m_ioc_capabilities & MPI2_IOCFACTS_CAPABILITY_MSI_X_INDEX) { + mpt->m_max_msix_vectors = ddi_get8(accessp, + &factsreply->MaxMSIxVectors); + } + + /* + * Set flag to check for SAS3 support. + */ + msgversion = ddi_get16(accessp, &factsreply->MsgVersion); + if (msgversion == MPI2_VERSION_02_05) { + mptsas_log(mpt, CE_NOTE, "?mpt_sas3%d SAS 3 Supported\n", + mpt->m_instance); + mpt->m_MPI25 = TRUE; + } else { + mptsas_log(mpt, CE_NOTE, "?mpt_sas3%d MPI Version 0x%x\n", + mpt->m_instance, msgversion); + } /* * Calculate max frames per request based on DMA S/G length. */ simple_sge_main = MPTSAS_MAX_FRAME_SGES64(mpt) - 1; simple_sge_next = mpt->m_req_frame_size / ! (mpt->m_MPI25 ? sizeof (MPI2_IEEE_SGE_SIMPLE64) : ! sizeof (MPI2_SGE_SIMPLE64)) - 1; mpt->m_max_request_frames = (MPTSAS_MAX_DMA_SEGS - simple_sge_main) / simple_sge_next + 1; if (((MPTSAS_MAX_DMA_SEGS - simple_sge_main) % simple_sge_next) > 1) {
*** 288,298 **** /* * Check if controller supports FW diag buffers and set flag to enable * each type. */ ! capabilities = ddi_get32(accessp, &factsreply->IOCCapabilities); if (capabilities & MPI2_IOCFACTS_CAPABILITY_DIAG_TRACE_BUFFER) { mpt->m_fw_diag_buffer_list[MPI2_DIAG_BUF_TYPE_TRACE].enabled = TRUE; } if (capabilities & MPI2_IOCFACTS_CAPABILITY_SNAPSHOT_BUFFER) { --- 346,356 ---- /* * Check if controller supports FW diag buffers and set flag to enable * each type. */ ! capabilities = mpt->m_ioc_capabilities; if (capabilities & MPI2_IOCFACTS_CAPABILITY_DIAG_TRACE_BUFFER) { mpt->m_fw_diag_buffer_list[MPI2_DIAG_BUF_TYPE_TRACE].enabled = TRUE; } if (capabilities & MPI2_IOCFACTS_CAPABILITY_SNAPSHOT_BUFFER) {
*** 601,610 **** --- 659,671 ---- init = (void *)memp; ddi_put8(accessp, &init->Function, MPI2_FUNCTION_IOC_INIT); ddi_put8(accessp, &init->WhoInit, MPI2_WHOINIT_HOST_DRIVER); ddi_put16(accessp, &init->MsgVersion, MPI2_VERSION); ddi_put16(accessp, &init->HeaderVersion, MPI2_HEADER_VERSION); + if (mpt->m_intr_type == DDI_INTR_TYPE_MSIX) { + ddi_put8(accessp, &init->HostMSIxVectors, mpt->m_intr_cnt); + } ddi_put16(accessp, &init->SystemRequestFrameSize, mpt->m_req_frame_size / 4); ddi_put16(accessp, &init->ReplyDescriptorPostQueueDepth, mpt->m_post_queue_depth); ddi_put16(accessp, &init->ReplyFreeQueueDepth,
*** 612,622 **** /* * These addresses are set using the DMA cookie addresses from when the * memory was allocated. Sense buffer hi address should be 0. */ ! ddi_put32(accessp, &init->SenseBufferAddressHigh, 0); ddi_put32(accessp, &init->SystemReplyAddressHigh, (uint32_t)(mpt->m_reply_frame_dma_addr >> 32)); ddi_put32(accessp, &init->SystemRequestFrameBaseAddress.High, (uint32_t)(mpt->m_req_frame_dma_addr >> 32)); ddi_put32(accessp, &init->SystemRequestFrameBaseAddress.Low, --- 673,684 ---- /* * These addresses are set using the DMA cookie addresses from when the * memory was allocated. Sense buffer hi address should be 0. */ ! ddi_put32(accessp, &init->SenseBufferAddressHigh, ! (uint32_t)(mpt->m_req_sense_dma_addr >> 32)); ddi_put32(accessp, &init->SystemReplyAddressHigh, (uint32_t)(mpt->m_reply_frame_dma_addr >> 32)); ddi_put32(accessp, &init->SystemRequestFrameBaseAddress.High, (uint32_t)(mpt->m_req_frame_dma_addr >> 32)); ddi_put32(accessp, &init->SystemRequestFrameBaseAddress.Low,