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,