diff --git a/sys/dev/mrsas/mrsas.c b/sys/dev/mrsas/mrsas.c index 7e327cdab814..8e93dcfb48bb 100644 --- a/sys/dev/mrsas/mrsas.c +++ b/sys/dev/mrsas/mrsas.c @@ -54,6 +54,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include /* @@ -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); } diff --git a/sys/dev/mrsas/mrsas.h b/sys/dev/mrsas/mrsas.h index 0798cc0c14cc..f9f236b68eb0 100644 --- a/sys/dev/mrsas/mrsas.h +++ b/sys/dev/mrsas/mrsas.h @@ -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; diff --git a/sys/dev/mrsas/mrsas_cam.c b/sys/dev/mrsas/mrsas_cam.c index 2a040291d035..f4d083889b92 100644 --- a/sys/dev/mrsas/mrsas_cam.c +++ b/sys/dev/mrsas/mrsas_cam.c @@ -49,8 +49,14 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include +#include /* XXX for pcpu.h */ +#include /* 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;