1
0
mirror of https://git.FreeBSD.org/src.git synced 2024-12-20 11:11:24 +00:00

Extended MSI-x vectors support for Invader and Fury(12Gb/s HBA).

This Driver will create multiple MSI-x vector depending upon what FW expose.
As of now 12 Gbp/s MR controller (Invader and Fury) expose 96 msix vector.
As of now 6 Gbp/s MR controller (Thunderbolt) expose 16 msix vector.

Reviewed by:	ambrisko
MFC after:		2 weeks
Sponsored by:	AVAGO Technologies
This commit is contained in:
Kashyap D Desai 2014-10-08 09:34:25 +00:00
parent 90012054d6
commit d18d1b472d
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=272739
3 changed files with 294 additions and 76 deletions

View File

@ -54,6 +54,7 @@ __FBSDID("$FreeBSD$");
#include <sys/types.h>
#include <sys/kthread.h>
#include <sys/taskqueue.h>
#include <sys/smp.h>
/*
@ -67,6 +68,8 @@ static d_ioctl_t mrsas_ioctl;
static struct mrsas_mgmt_info mrsas_mgmt_info;
static struct mrsas_ident *mrsas_find_ident(device_t);
static int mrsas_setup_msix(struct mrsas_softc *sc);
static int mrsas_allocate_msix(struct mrsas_softc *sc);
static void mrsas_shutdown_ctlr(struct mrsas_softc *sc, u_int32_t opcode);
static void mrsas_flush_cache(struct mrsas_softc *sc);
static void mrsas_reset_reply_desc(struct mrsas_softc *sc);
@ -80,7 +83,7 @@ static int mrsas_setup_irq(struct mrsas_softc *sc);
static int mrsas_alloc_mem(struct mrsas_softc *sc);
static int mrsas_init_fw(struct mrsas_softc *sc);
static int mrsas_setup_raidmap(struct mrsas_softc *sc);
static int mrsas_complete_cmd(struct mrsas_softc *sc);
static int mrsas_complete_cmd(struct mrsas_softc *sc, u_int32_t MSIxIndex);
static int mrsas_clear_intr(struct mrsas_softc *sc);
static int mrsas_get_ctrl_info(struct mrsas_softc *sc,
struct mrsas_ctrl_info *ctrl_info);
@ -151,7 +154,6 @@ static int mrsas_alloc_evt_log_info_cmd(struct mrsas_softc *sc);
static void mrsas_free_evt_log_info_cmd(struct mrsas_softc *sc);
SYSCTL_NODE(_hw, OID_AUTO, mrsas, CTLFLAG_RD, 0, "MRSAS Driver Parameters");
/**
* PCI device struct and table
*
@ -709,8 +711,63 @@ static int mrsas_start_aen(struct mrsas_softc *sc)
return mrsas_register_aen(sc, eli.newest_seq_num + 1,
class_locale.word);
}
/**
* mrsas_setup_msix: Allocate MSI-x vectors
* @sc: Adapter soft state
*/
static int mrsas_setup_msix(struct mrsas_softc *sc)
{
int i;
for (i = 0; i < sc->msix_vectors; i++) {
sc->irq_context[i].sc = sc;
sc->irq_context[i].MSIxIndex = i;
sc->irq_id[i] = i + 1;
sc->mrsas_irq[i] = bus_alloc_resource_any
(sc->mrsas_dev, SYS_RES_IRQ, &sc->irq_id[i]
, RF_ACTIVE);
if (sc->mrsas_irq[i] == NULL) {
device_printf(sc->mrsas_dev, "Can't allocate MSI-x\n");
goto irq_alloc_failed;
}
if (bus_setup_intr(sc->mrsas_dev,
sc->mrsas_irq[i],
INTR_MPSAFE|INTR_TYPE_CAM,
NULL, mrsas_isr, &sc->irq_context[i],
&sc->intr_handle[i])) {
device_printf(sc->mrsas_dev,
"Cannot set up MSI-x interrupt handler\n");
goto irq_alloc_failed;
}
}
return SUCCESS;
irq_alloc_failed:
mrsas_teardown_intr(sc);
return (FAIL);
}
/**
* mrsas_allocate_msix: Setup MSI-x vectors
* @sc: Adapter soft state
*/
static int mrsas_allocate_msix(struct mrsas_softc *sc)
{
if (pci_alloc_msix(sc->mrsas_dev, &sc->msix_vectors) == 0) {
device_printf(sc->mrsas_dev, "Using MSI-X with %d number"
" of vectors\n", sc->msix_vectors);
} else {
device_printf(sc->mrsas_dev, "MSI-x setup failed\n");
goto irq_alloc_failed;
}
return SUCCESS;
irq_alloc_failed:
mrsas_teardown_intr(sc);
return (FAIL);
}
/**
* mrsas_attach: PCI entry point
* input: device struct pointer
@ -784,6 +841,8 @@ static int mrsas_attach(device_t dev)
sc->adprecovery = MRSAS_HBA_OPERATIONAL;
sc->UnevenSpanSupport = 0;
sc->msix_enable = 0;
/* Initialize Firmware */
if (mrsas_init_fw(sc) != SUCCESS) {
goto attach_fail_fw;
@ -794,6 +853,7 @@ static int mrsas_attach(device_t dev)
goto attach_fail_cam;
}
/* Register IRQs */
if (mrsas_setup_irq(sc) != SUCCESS) {
goto attach_fail_irq;
@ -838,7 +898,9 @@ static int mrsas_attach(device_t dev)
attach_fail_cam:
mrsas_cam_detach(sc);
attach_fail_fw:
//attach_fail_raidmap:
/* if MSIX vector is allocated and FW Init FAILED then release MSIX */
if (sc->msix_enable == 1)
pci_release_msi(sc->mrsas_dev);
mrsas_free_mem(sc);
mtx_destroy(&sc->sim_lock);
mtx_destroy(&sc->aen_lock);
@ -1081,11 +1143,28 @@ void mrsas_free_mem(struct mrsas_softc *sc)
*/
void mrsas_teardown_intr(struct mrsas_softc *sc)
{
if (sc->intr_handle)
bus_teardown_intr(sc->mrsas_dev, sc->mrsas_irq, sc->intr_handle);
if (sc->mrsas_irq != NULL)
bus_release_resource(sc->mrsas_dev, SYS_RES_IRQ, sc->irq_id, sc->mrsas_irq);
sc->intr_handle = NULL;
int i;
if (!sc->msix_enable) {
if (sc->intr_handle[0])
bus_teardown_intr(sc->mrsas_dev, sc->mrsas_irq[0], sc->intr_handle[0]);
if (sc->mrsas_irq[0] != NULL)
bus_release_resource(sc->mrsas_dev, SYS_RES_IRQ, sc->irq_id[0], sc->mrsas_irq[0]);
sc->intr_handle[0] = NULL;
} else {
for (i = 0; i < sc->msix_vectors; i++) {
if (sc->intr_handle[i])
bus_teardown_intr(sc->mrsas_dev, sc->mrsas_irq[i],
sc->intr_handle[i]);
if (sc->mrsas_irq[i] != NULL)
bus_release_resource(sc->mrsas_dev, SYS_RES_IRQ,
sc->irq_id[i], sc->mrsas_irq[i]);
sc->intr_handle[i] = NULL;
}
pci_release_msi(sc->mrsas_dev);
}
}
/**
@ -1195,19 +1274,29 @@ mrsas_ioctl(struct cdev *dev, u_long cmd, caddr_t arg, int flag, d_thread_t *td)
*/
static int mrsas_setup_irq(struct mrsas_softc *sc)
{
sc->irq_id = 0;
sc->mrsas_irq = bus_alloc_resource_any(sc->mrsas_dev, SYS_RES_IRQ,
&sc->irq_id, RF_SHAREABLE | RF_ACTIVE);
if (sc->mrsas_irq == NULL){
device_printf(sc->mrsas_dev, "Cannot allocate interrupt\n");
return (FAIL);
}
if (bus_setup_intr(sc->mrsas_dev, sc->mrsas_irq, INTR_MPSAFE|INTR_TYPE_CAM,
NULL, mrsas_isr, sc, &sc->intr_handle)) {
device_printf(sc->mrsas_dev, "Cannot set up interrupt\n");
return (FAIL);
}
if (sc->msix_enable && (mrsas_setup_msix(sc) == SUCCESS))
device_printf(sc->mrsas_dev, "MSI-x interrupts setup success\n");
else {
device_printf(sc->mrsas_dev, "Fall back to legacy interrupt\n");
sc->irq_context[0].sc = sc;
sc->irq_context[0].MSIxIndex = 0;
sc->irq_id[0] = 0;
sc->mrsas_irq[0] = bus_alloc_resource_any(sc->mrsas_dev,
SYS_RES_IRQ, &sc->irq_id[0], RF_SHAREABLE | RF_ACTIVE);
if (sc->mrsas_irq[0] == NULL){
device_printf(sc->mrsas_dev, "Cannot allocate legcay"
"interrupt\n");
return (FAIL);
}
if (bus_setup_intr(sc->mrsas_dev, sc->mrsas_irq[0],
INTR_MPSAFE|INTR_TYPE_CAM, NULL, mrsas_isr,
&sc->irq_context[0], &sc->intr_handle[0])) {
device_printf(sc->mrsas_dev, "Cannot set up legacy"
"interrupt\n");
return (FAIL);
}
}
return (0);
}
@ -1221,16 +1310,16 @@ static int mrsas_setup_irq(struct mrsas_softc *sc)
*/
void mrsas_isr(void *arg)
{
struct mrsas_softc *sc = (struct mrsas_softc *)arg;
int status;
struct mrsas_irq_context *irq_context = (struct mrsas_irq_context *)arg;
struct mrsas_softc *sc = irq_context->sc;
int status = 0;
/* Clear FW state change interrupt */
status = mrsas_clear_intr(sc);
if (!sc->msix_vectors) {
status = mrsas_clear_intr(sc);
if (!status)
return;
}
/* Not our interrupt */
if (!status)
return;
/* If we are resetting, bail */
if (test_bit(MRSAS_FUSION_IN_RESET, &sc->reset_flags)) {
printf(" Entered into ISR when OCR is going active. \n");
@ -1238,7 +1327,7 @@ void mrsas_isr(void *arg)
return;
}
/* Process for reply request and clear response interrupt */
if (mrsas_complete_cmd(sc) != SUCCESS)
if (mrsas_complete_cmd(sc, irq_context->MSIxIndex) != SUCCESS)
mrsas_clear_intr(sc);
return;
@ -1255,7 +1344,7 @@ void mrsas_isr(void *arg)
* the command type and perform the appropriate action. Before we
* return, we clear the response interrupt.
*/
static int mrsas_complete_cmd(struct mrsas_softc *sc)
static int mrsas_complete_cmd(struct mrsas_softc *sc, u_int32_t MSIxIndex)
{
Mpi2ReplyDescriptorsUnion_t *desc;
MPI2_SCSI_IO_SUCCESS_REPLY_DESCRIPTOR *reply_desc;
@ -1276,7 +1365,9 @@ static int mrsas_complete_cmd(struct mrsas_softc *sc)
return (DONE);
desc = sc->reply_desc_mem;
desc += sc->last_reply_idx;
//desc += sc->last_reply_idx[0];
desc += ((MSIxIndex * sc->reply_alloc_sz)/sizeof(MPI2_REPLY_DESCRIPTORS_UNION))
+ sc->last_reply_idx[MSIxIndex];
reply_desc = (MPI2_SCSI_IO_SUCCESS_REPLY_DESCRIPTOR *)desc;
@ -1321,18 +1412,19 @@ static int mrsas_complete_cmd(struct mrsas_softc *sc)
break;
}
sc->last_reply_idx++;
if (sc->last_reply_idx >= sc->reply_q_depth)
sc->last_reply_idx = 0;
sc->last_reply_idx[MSIxIndex]++;
if (sc->last_reply_idx[MSIxIndex] >= sc->reply_q_depth)
sc->last_reply_idx[MSIxIndex] = 0;
desc->Words = ~((uint64_t)0x00); /* set it back to all 0xFFFFFFFFs */
num_completed++;
threshold_reply_count++;
/* Get the next reply descriptor */
if (!sc->last_reply_idx)
if (!sc->last_reply_idx[MSIxIndex]){
desc = sc->reply_desc_mem;
else
desc += ((MSIxIndex * sc->reply_alloc_sz)/sizeof(MPI2_REPLY_DESCRIPTORS_UNION));
} else
desc++;
reply_desc = (MPI2_SCSI_IO_SUCCESS_REPLY_DESCRIPTOR *)desc;
@ -1349,18 +1441,40 @@ static int mrsas_complete_cmd(struct mrsas_softc *sc)
* completed.
*/
if (threshold_reply_count >= THRESHOLD_REPLY_COUNT) {
mrsas_write_reg(sc, offsetof(mrsas_reg_set, reply_post_host_index),
sc->last_reply_idx);
threshold_reply_count = 0;
if (sc->msix_enable) {
if ((sc->device_id == MRSAS_INVADER) ||
(sc->device_id == MRSAS_FURY))
mrsas_write_reg(sc, sc->msix_reg_offset[MSIxIndex/8],
((MSIxIndex & 0x7) << 24) |
sc->last_reply_idx[MSIxIndex]);
else
mrsas_write_reg(sc, sc->msix_reg_offset[0], (MSIxIndex << 24) |
sc->last_reply_idx[MSIxIndex]);
} else
mrsas_write_reg(sc, offsetof(mrsas_reg_set,
reply_post_host_index),sc->last_reply_idx[0]);
threshold_reply_count = 0;
}
}
}
/* No match, just return */
if (num_completed == 0)
return (DONE);
/* Clear response interrupt */
mrsas_write_reg(sc, offsetof(mrsas_reg_set, reply_post_host_index),sc->last_reply_idx);
if (sc->msix_enable) {
if ((sc->device_id == MRSAS_INVADER) ||
(sc->device_id == MRSAS_FURY)){
mrsas_write_reg(sc, sc->msix_reg_offset[MSIxIndex/8],
((MSIxIndex & 0x7) << 24) |
sc->last_reply_idx[MSIxIndex]);
} else
mrsas_write_reg(sc, sc->msix_reg_offset[0], (MSIxIndex << 24) |
sc->last_reply_idx[MSIxIndex]);
} else
mrsas_write_reg(sc, offsetof(mrsas_reg_set,
reply_post_host_index),sc->last_reply_idx[0]);
return(0);
}
@ -1423,7 +1537,7 @@ void mrsas_map_mpt_cmd_status(struct mrsas_mpt_cmd *cmd, u_int8_t status, u_int8
static int mrsas_alloc_mem(struct mrsas_softc *sc)
{
u_int32_t verbuf_size, io_req_size, reply_desc_size, sense_size,
chain_frame_size, evt_detail_size;
chain_frame_size, evt_detail_size, count;
/*
* Allocate parent DMA tag
@ -1537,10 +1651,11 @@ static int mrsas_alloc_mem(struct mrsas_softc *sc)
return (ENOMEM);
}
count = sc->msix_vectors > 0 ? sc->msix_vectors : 1;
/*
* Allocate Reply Descriptor Array
*/
reply_desc_size = sc->reply_alloc_sz;
reply_desc_size = sc->reply_alloc_sz * count;
if (bus_dma_tag_create( sc->mrsas_parent_tag, // parent
16, 0, // algnmnt, boundary
BUS_SPACE_MAXADDR_32BIT,// lowaddr
@ -1796,13 +1911,15 @@ static int mrsas_setup_raidmap(struct mrsas_softc *sc)
*/
static int mrsas_init_fw(struct mrsas_softc *sc)
{
int ret, loop, ocr = 0;
u_int32_t max_sectors_1;
u_int32_t max_sectors_2;
u_int32_t tmp_sectors;
struct mrsas_ctrl_info *ctrl_info;
int ret, ocr = 0;
u_int32_t scratch_pad_2;
int msix_enable = 0;
int fw_msix_count = 0;
/* Make sure Firmware is ready */
ret = mrsas_transition_to_ready(sc, ocr);
@ -1810,7 +1927,57 @@ static int mrsas_init_fw(struct mrsas_softc *sc)
return(ret);
}
/* Get operational params, sge flags, send init cmd to ctlr */
/* MSI-x index 0- reply post host index register */
sc->msix_reg_offset[0] = MPI2_REPLY_POST_HOST_INDEX_OFFSET;
/* Check if MSI-X is supported while in ready state */
msix_enable = (mrsas_read_reg(sc, offsetof(mrsas_reg_set, outbound_scratch_pad)) & 0x4000000) >> 0x1a;
if (msix_enable) {
scratch_pad_2 = mrsas_read_reg(sc, offsetof(mrsas_reg_set,
outbound_scratch_pad_2));
/* Check max MSI-X vectors */
if (sc->device_id == MRSAS_TBOLT) {
sc->msix_vectors = (scratch_pad_2
& MR_MAX_REPLY_QUEUES_OFFSET) + 1;
fw_msix_count = sc->msix_vectors;
} else {
/* Invader/Fury supports 96 MSI-X vectors */
sc->msix_vectors = ((scratch_pad_2
& MR_MAX_REPLY_QUEUES_EXT_OFFSET)
>> MR_MAX_REPLY_QUEUES_EXT_OFFSET_SHIFT) + 1;
fw_msix_count = sc->msix_vectors;
/* Save 1-15 reply post index address to local
* memory
* Index 0 is already saved from reg offset
* MPI2_REPLY_POST_HOST_INDEX_OFFSET
*/
for (loop = 1; loop < MR_MAX_MSIX_REG_ARRAY;
loop++) {
sc->msix_reg_offset[loop] =
MPI2_SUP_REPLY_POST_HOST_INDEX_OFFSET +
(loop * 0x10);
}
}
/* Don't bother allocating more MSI-X vectors than cpus */
sc->msix_vectors = min(sc->msix_vectors,
mp_ncpus);
/* Allocate MSI-x vectors */
if (mrsas_allocate_msix(sc) == SUCCESS)
sc->msix_enable = 1;
else
sc->msix_enable = 0;
device_printf(sc->mrsas_dev, "FW supports <%d> MSIX vector,"
"Online CPU %d Current MSIX <%d>\n",
fw_msix_count, mp_ncpus, sc->msix_vectors);
}
/* Get operational params, sge flags, send init cmd to ctlr */
if (mrsas_init_adapter(sc) != SUCCESS){
device_printf(sc->mrsas_dev, "Adapter initialize Fail.\n");
return(1);
@ -1907,6 +2074,7 @@ int mrsas_init_adapter(struct mrsas_softc *sc)
uint32_t status;
u_int32_t max_cmd;
int ret;
int i = 0;
/* Read FW status register */
status = mrsas_read_reg(sc, offsetof(mrsas_reg_set, outbound_scratch_pad));
@ -1919,7 +2087,7 @@ int mrsas_init_adapter(struct mrsas_softc *sc)
max_cmd = sc->max_fw_cmds;
/* Determine allocation size of command frames */
sc->reply_q_depth = ((max_cmd *2 +1 +15)/16*16);
sc->reply_q_depth = ((max_cmd +1 +15)/16*16);
sc->request_alloc_sz = sizeof(MRSAS_REQUEST_DESCRIPTOR_UNION) * max_cmd;
sc->reply_alloc_sz = sizeof(MPI2_REPLY_DESCRIPTORS_UNION) * (sc->reply_q_depth);
sc->io_frames_alloc_sz = MRSAS_MPI2_RAID_DEFAULT_IO_FRAME_SIZE + (MRSAS_MPI2_RAID_DEFAULT_IO_FRAME_SIZE * (max_cmd + 1));
@ -1936,7 +2104,9 @@ int mrsas_init_adapter(struct mrsas_softc *sc)
sc->chain_offset_io_request = (MRSAS_MPI2_RAID_DEFAULT_IO_FRAME_SIZE -
sizeof(MPI2_SGE_IO_UNION))/16;
sc->last_reply_idx = 0;
int count = sc->msix_vectors > 0 ? sc->msix_vectors : 1;
for (i = 0 ; i < count; i++)
sc->last_reply_idx[i] = 0;
ret = mrsas_alloc_mem(sc);
if (ret != SUCCESS)
@ -1949,6 +2119,7 @@ int mrsas_init_adapter(struct mrsas_softc *sc)
ret = mrsas_ioc_init(sc);
if (ret != SUCCESS)
return(ret);
return(0);
@ -2042,12 +2213,21 @@ int mrsas_ioc_init(struct mrsas_softc *sc)
IOCInitMsg->ReplyDescriptorPostQueueDepth = sc->reply_q_depth;
IOCInitMsg->ReplyDescriptorPostQueueAddress = sc->reply_desc_phys_addr;
IOCInitMsg->SystemRequestFrameBaseAddress = sc->io_request_phys_addr;
IOCInitMsg->HostMSIxVectors = (sc->msix_vectors > 0 ? sc->msix_vectors : 0);
init_frame = (struct mrsas_init_frame *)sc->ioc_init_mem;
init_frame->cmd = MFI_CMD_INIT;
init_frame->cmd_status = 0xFF;
init_frame->flags |= MFI_FRAME_DONT_POST_IN_REPLY_QUEUE;
/* driver support Extended MSIX */
if ((sc->device_id == MRSAS_INVADER) ||
(sc->device_id == MRSAS_FURY)) {
init_frame->driver_operations.
mfi_capabilities.support_additional_msix = 1;
}
if (sc->verbuf_mem) {
snprintf((char *)sc->verbuf_mem, strlen(MRSAS_VERSION)+2,"%s\n",
MRSAS_VERSION);
@ -2113,7 +2293,7 @@ int mrsas_ioc_init(struct mrsas_softc *sc)
int mrsas_alloc_mpt_cmds(struct mrsas_softc *sc)
{
int i, j;
u_int32_t max_cmd;
u_int32_t max_cmd, count;
struct mrsas_mpt_cmd *cmd;
pMpi2ReplyDescriptorsUnion_t reply_desc;
u_int32_t offset, chain_offset, sense_offset;
@ -2183,7 +2363,8 @@ int mrsas_alloc_mpt_cmds(struct mrsas_softc *sc)
/* Initialize reply descriptor array to 0xFFFFFFFF */
reply_desc = sc->reply_desc_mem;
for (i = 0; i < sc->reply_q_depth; i++, reply_desc++) {
count = sc->msix_vectors > 0 ? sc->msix_vectors : 1;
for (i = 0; i < sc->reply_q_depth * count ; i++, reply_desc++) {
reply_desc->Words = MRSAS_ULONG_MAX;
}
return(0);
@ -2400,11 +2581,14 @@ mrsas_ocr_thread(void *arg)
*/
void mrsas_reset_reply_desc(struct mrsas_softc *sc)
{
int i;
int i, count;
pMpi2ReplyDescriptorsUnion_t reply_desc;
sc->last_reply_idx = 0;
reply_desc = sc->reply_desc_mem;
count = sc->msix_vectors > 0 ? sc->msix_vectors : 1;
for (i = 0 ; i < count ; i++)
sc->last_reply_idx[i] = 0;
reply_desc = sc->reply_desc_mem;
for (i = 0; i < sc->reply_q_depth; i++, reply_desc++) {
reply_desc->Words = MRSAS_ULONG_MAX;
}
@ -2641,7 +2825,8 @@ void mrsas_kill_hba (struct mrsas_softc *sc)
int mrsas_wait_for_outstanding(struct mrsas_softc *sc)
{
int i, outstanding, retval = 0;
u_int32_t fw_state;
u_int32_t fw_state, count, MSIxIndex;
for (i = 0; i < MRSAS_RESET_WAIT_TIME; i++) {
if (sc->remove_in_progress) {
@ -2666,7 +2851,9 @@ int mrsas_wait_for_outstanding(struct mrsas_softc *sc)
if (!(i % MRSAS_RESET_NOTICE_INTERVAL)) {
mrsas_dprint(sc, MRSAS_OCR, "[%2d]waiting for %d "
"commands to complete\n",i,outstanding);
mrsas_complete_cmd(sc);
count = sc->msix_vectors > 0 ? sc->msix_vectors : 1;
for (MSIxIndex = 0 ; MSIxIndex < count; MSIxIndex++)
mrsas_complete_cmd(sc, MSIxIndex);
}
DELAY(1000 * 1000);
}

View File

@ -110,6 +110,7 @@ __FBSDID("$FreeBSD$");
#define MRSAS_IO_TIMEOUT 180000 /* 180 second timeout */
#define MRSAS_LDIO_QUEUE_DEPTH 70 /* 70 percent as default */
#define THRESHOLD_REPLY_COUNT 50
#define MAX_MSIX_COUNT 128
/*
Boolean types
@ -1959,6 +1960,16 @@ struct mrsas_ctrl_info {
#define MRSAS_DEFAULT_CMD_TIMEOUT 90
#define MRSAS_THROTTLE_QUEUE_DEPTH 16
/*
* MSI-x regsiters offset defines
*/
#define MPI2_SUP_REPLY_POST_HOST_INDEX_OFFSET (0x0000030C)
#define MPI2_REPLY_POST_HOST_INDEX_OFFSET (0x0000006C)
#define MR_MAX_REPLY_QUEUES_OFFSET (0x0000001F)
#define MR_MAX_REPLY_QUEUES_EXT_OFFSET (0x003FC000)
#define MR_MAX_REPLY_QUEUES_EXT_OFFSET_SHIFT 14
#define MR_MAX_MSIX_REG_ARRAY 16
/*
* FW reports the maximum of number of commands that it can accept (maximum
* commands that can be outstanding) at any time. The driver must report a
@ -1968,7 +1979,7 @@ struct mrsas_ctrl_info {
*/
#define MRSAS_INT_CMDS 32
#define MRSAS_SKINNY_INT_CMDS 5
#define MRSAS_MAX_MSIX_QUEUES 16
#define MRSAS_MAX_MSIX_QUEUES 128
/*
* FW can accept both 32 and 64 bit SGLs. We want to allocate 32/64 bit
@ -1993,6 +2004,17 @@ struct mrsas_ctrl_info {
#define MFI_1068_FW_HANDSHAKE_OFFSET 0x64
#define MFI_1068_FW_READY 0xDDDD0000
typedef union _MFI_CAPABILITIES {
struct {
u_int32_t support_fp_remote_lun:1;
u_int32_t support_additional_msix:1;
u_int32_t support_fastpath_wb:1;
u_int32_t support_max_255lds:1;
u_int32_t reserved:28;
} mfi_capabilities;
u_int32_t reg;
} MFI_CAPABILITIES;
#pragma pack(1)
struct mrsas_sge32 {
u_int32_t phys_addr;
@ -2035,18 +2057,6 @@ struct mrsas_header {
};
#pragma pack()
typedef union _MFI_CAPABILITIES {
struct {
u_int32_t support_fp_remote_lun:1;
u_int32_t support_additional_msix:1;
u_int32_t support_fastpath_wb:1;
u_int32_t support_max_255lds:1;
u_int32_t reserved:28;
} mfi_capabilities;
u_int32_t reg;
} MFI_CAPABILITIES;
#pragma pack(1)
struct mrsas_init_frame {
u_int8_t cmd; /*00h */
@ -2162,8 +2172,7 @@ struct mrsas_abort_frame {
u_int8_t cmd_status; /*02h */
u_int8_t reserved_1; /*03h */
u_int32_t reserved_2; /*04h */
MFI_CAPABILITIES driver_operations; /*04h */
u_int32_t context; /*08h */
u_int32_t pad_0; /*0Ch */
@ -2419,6 +2428,11 @@ struct mrsas_evt_detail {
} __packed;
struct mrsas_irq_context {
struct mrsas_softc *sc;
uint32_t MSIxIndex;
};
/* Controller management info added to support Linux Emulator */
#define MAX_MGMT_ADAPTERS 1024
@ -2479,9 +2493,13 @@ struct mrsas_softc {
struct mtx aen_lock; // aen lock
uint32_t max_fw_cmds; // Max commands from FW
uint32_t max_num_sge; // Max number of SGEs
struct resource *mrsas_irq; // interrupt interface window
void *intr_handle; // handle
int irq_id; // intr resource id
struct resource *mrsas_irq[MAX_MSIX_COUNT]; // interrupt interface window
void *intr_handle[MAX_MSIX_COUNT]; // handle
int irq_id[MAX_MSIX_COUNT]; // intr resource id
struct mrsas_irq_context irq_context[MAX_MSIX_COUNT];
int msix_vectors; // Max msix vectors
int msix_enable; // MSI-x support
uint32_t msix_reg_offset[16];
struct mrsas_mpt_cmd **mpt_cmd_list;
struct mrsas_mfi_cmd **mfi_cmd_list;
TAILQ_HEAD(, mrsas_mpt_cmd) mrsas_mpt_cmd_list_head;
@ -2492,7 +2510,7 @@ struct mrsas_softc {
bus_addr_t io_request_frames_phys;
u_int8_t *io_request_frames;
bus_addr_t reply_frames_desc_phys;
u_int16_t last_reply_idx;
u_int16_t last_reply_idx[MAX_MSIX_COUNT];
u_int32_t reply_q_depth;
u_int32_t request_alloc_sz;
u_int32_t reply_alloc_sz;

View File

@ -49,8 +49,14 @@ __FBSDID("$FreeBSD$");
#include <cam/scsi/scsi_all.h>
#include <cam/scsi/scsi_message.h>
#include <sys/taskqueue.h>
#include <sys/kernel.h>
#include <sys/time.h> /* XXX for pcpu.h */
#include <sys/pcpu.h> /* XXX for PCPU_GET */
#define smp_processor_id() PCPU_GET(cpuid)
/*
* Function prototypes
*/
@ -794,7 +800,11 @@ int mrsas_setup_io(struct mrsas_softc *sc, struct mrsas_mpt_cmd *cmd,
fp_possible = io_info.fpOkForIo;
}
if (fp_possible) {
cmd->request_desc->SCSIIO.MSIxIndex =
sc->msix_vectors ? smp_processor_id() % sc->msix_vectors : 0;
if (fp_possible) {
mrsas_set_pd_lba(io_request, csio->cdb_len, &io_info, ccb, map_ptr,
start_lba_lo, ld_block_size);
io_request->Function = MPI2_FUNCTION_SCSI_IO_REQUEST;
@ -881,6 +891,9 @@ int mrsas_build_dcdb(struct mrsas_softc *sc, struct mrsas_mpt_cmd *cmd,
MRSAS_REQ_DESCRIPT_FLAGS_TYPE_SHIFT);
cmd->request_desc->SCSIIO.DevHandle =
map_ptr->raidMap.devHndlInfo[device_id].curDevHdl;
cmd->request_desc->SCSIIO.MSIxIndex =
sc->msix_vectors ? smp_processor_id() % sc->msix_vectors : 0;
}
else {
io_request->Function = MRSAS_MPI2_FUNCTION_LD_IO_REQUEST;