diff options
-rw-r--r-- | sys/dev/mrsas/mrsas.c | 690 | ||||
-rw-r--r-- | sys/dev/mrsas/mrsas.h | 63 | ||||
-rw-r--r-- | sys/dev/mrsas/mrsas_cam.c | 282 | ||||
-rw-r--r-- | sys/dev/mrsas/mrsas_fp.c | 21 | ||||
-rw-r--r-- | sys/dev/mrsas/mrsas_ioctl.c | 25 |
5 files changed, 819 insertions, 262 deletions
diff --git a/sys/dev/mrsas/mrsas.c b/sys/dev/mrsas/mrsas.c index f72e0fc..bc0c279 100644 --- a/sys/dev/mrsas/mrsas.c +++ b/sys/dev/mrsas/mrsas.c @@ -48,6 +48,7 @@ __FBSDID("$FreeBSD$"); #include <sys/sysctl.h> #include <sys/types.h> +#include <sys/sysent.h> #include <sys/kthread.h> #include <sys/taskqueue.h> #include <sys/smp.h> @@ -63,6 +64,7 @@ static d_write_t mrsas_write; static d_ioctl_t mrsas_ioctl; static d_poll_t mrsas_poll; +static void mrsas_ich_startup(void *arg); 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); @@ -80,7 +82,8 @@ 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, u_int32_t MSIxIndex); +static void megasas_setup_jbod_map(struct mrsas_softc *sc); +static int megasas_sync_pd_seq_num(struct mrsas_softc *sc, boolean_t pend); static int mrsas_clear_intr(struct mrsas_softc *sc); static int mrsas_get_ctrl_info(struct mrsas_softc *sc); static void mrsas_update_ext_vd_details(struct mrsas_softc *sc); @@ -104,8 +107,9 @@ int mrsas_ioc_init(struct mrsas_softc *sc); int mrsas_bus_scan(struct mrsas_softc *sc); int mrsas_issue_dcmd(struct mrsas_softc *sc, struct mrsas_mfi_cmd *cmd); int mrsas_issue_polled(struct mrsas_softc *sc, struct mrsas_mfi_cmd *cmd); -int mrsas_reset_ctrl(struct mrsas_softc *sc); -int mrsas_wait_for_outstanding(struct mrsas_softc *sc); +int mrsas_reset_ctrl(struct mrsas_softc *sc, u_int8_t reset_reason); +int mrsas_wait_for_outstanding(struct mrsas_softc *sc, u_int8_t check_reason); +int mrsas_complete_cmd(struct mrsas_softc *sc, u_int32_t MSIxIndex); int mrsas_issue_blocked_cmd(struct mrsas_softc *sc, struct mrsas_mfi_cmd *cmd); @@ -182,6 +186,8 @@ MRSAS_CTLR_ID device_table[] = { {0x1000, MRSAS_TBOLT, 0xffff, 0xffff, "AVAGO Thunderbolt SAS Controller"}, {0x1000, MRSAS_INVADER, 0xffff, 0xffff, "AVAGO Invader SAS Controller"}, {0x1000, MRSAS_FURY, 0xffff, 0xffff, "AVAGO Fury SAS Controller"}, + {0x1000, MRSAS_INTRUDER, 0xffff, 0xffff, "AVAGO Intruder SAS Controller"}, + {0x1000, MRSAS_INTRUDER_24, 0xffff, 0xffff, "AVAGO Intruder_24 SAS Controller"}, {0, 0, 0, 0, NULL} }; @@ -553,6 +559,7 @@ mrsas_get_seq_num(struct mrsas_softc *sc, { struct mrsas_mfi_cmd *cmd; struct mrsas_dcmd_frame *dcmd; + u_int8_t do_ocr = 1, retcode = 0; cmd = mrsas_get_mfi_cmd(sc); @@ -580,16 +587,24 @@ mrsas_get_seq_num(struct mrsas_softc *sc, dcmd->sgl.sge32[0].phys_addr = sc->el_info_phys_addr; dcmd->sgl.sge32[0].length = sizeof(struct mrsas_evt_log_info); - mrsas_issue_blocked_cmd(sc, cmd); + retcode = mrsas_issue_blocked_cmd(sc, cmd); + if (retcode == ETIMEDOUT) + goto dcmd_timeout; + do_ocr = 0; /* * Copy the data back into callers buffer */ memcpy(eli, sc->el_info_mem, sizeof(struct mrsas_evt_log_info)); mrsas_free_evt_log_info_cmd(sc); - mrsas_release_mfi_cmd(cmd); - return 0; +dcmd_timeout: + if (do_ocr) + sc->do_timedout_reset = MFI_DCMD_TIMEOUT_OCR; + else + mrsas_release_mfi_cmd(cmd); + + return retcode; } @@ -811,7 +826,8 @@ mrsas_attach(device_t dev) { struct mrsas_softc *sc = device_get_softc(dev); uint32_t cmd, bar, error; - struct cdev *linux_dev; + + memset(sc, 0, sizeof(struct mrsas_softc)); /* Look up our softc and initialize its fields. */ sc->mrsas_dev = dev; @@ -852,12 +868,6 @@ mrsas_attach(device_t dev) mtx_init(&sc->mfi_cmd_pool_lock, "mrsas_mfi_cmd_pool_lock", NULL, MTX_DEF); mtx_init(&sc->raidmap_lock, "mrsas_raidmap_lock", NULL, MTX_DEF); - /* - * Intialize a counting Semaphore to take care no. of concurrent - * IOCTLs - */ - sema_init(&sc->ioctl_count_sema, MRSAS_MAX_MFI_CMDS - 5, IOCTL_SEMA_DESCRIPTION); - /* Intialize linked list */ TAILQ_INIT(&sc->mrsas_mpt_cmd_list_head); TAILQ_INIT(&sc->mrsas_mfi_cmd_list_head); @@ -866,16 +876,6 @@ mrsas_attach(device_t dev) sc->io_cmds_highwater = 0; - /* Create a /dev entry for this device. */ - sc->mrsas_cdev = make_dev(&mrsas_cdevsw, device_get_unit(dev), UID_ROOT, - GID_OPERATOR, (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP), "mrsas%u", - device_get_unit(dev)); - if (device_get_unit(dev) == 0) - make_dev_alias_p(MAKEDEV_CHECKNAME, &linux_dev, sc->mrsas_cdev, - "megaraid_sas_ioctl_node"); - if (sc->mrsas_cdev) - sc->mrsas_cdev->si_drv1 = sc; - sc->adprecovery = MRSAS_HBA_OPERATIONAL; sc->UnevenSpanSupport = 0; @@ -885,7 +885,7 @@ mrsas_attach(device_t dev) if (mrsas_init_fw(sc) != SUCCESS) { goto attach_fail_fw; } - /* Register SCSI mid-layer */ + /* Register mrsas to CAM layer */ if ((mrsas_cam_attach(sc) != SUCCESS)) { goto attach_fail_cam; } @@ -893,38 +893,28 @@ mrsas_attach(device_t dev) if (mrsas_setup_irq(sc) != SUCCESS) { goto attach_fail_irq; } - /* Enable Interrupts */ - mrsas_enable_intr(sc); - error = mrsas_kproc_create(mrsas_ocr_thread, sc, &sc->ocr_thread, 0, 0, "mrsas_ocr%d", device_get_unit(sc->mrsas_dev)); if (error) { - printf("Error %d starting rescan thread\n", error); - goto attach_fail_irq; - } - mrsas_setup_sysctl(sc); - - /* Initiate AEN (Asynchronous Event Notification) */ - - if (mrsas_start_aen(sc)) { - printf("Error: start aen failed\n"); - goto fail_start_aen; + device_printf(sc->mrsas_dev, "Error %d starting OCR thread\n", error); + goto attach_fail_ocr_thread; } /* - * Add this controller to mrsas_mgmt_info structure so that it can be - * exported to management applications + * After FW initialization and OCR thread creation + * we will defer the cdev creation, AEN setup on ICH callback */ - if (device_get_unit(dev) == 0) - memset(&mrsas_mgmt_info, 0, sizeof(mrsas_mgmt_info)); - - mrsas_mgmt_info.count++; - mrsas_mgmt_info.sc_ptr[mrsas_mgmt_info.max_index] = sc; - mrsas_mgmt_info.max_index++; - - return (0); + sc->mrsas_ich.ich_func = mrsas_ich_startup; + sc->mrsas_ich.ich_arg = sc; + if (config_intrhook_establish(&sc->mrsas_ich) != 0) { + device_printf(sc->mrsas_dev, "Config hook is already established\n"); + } + mrsas_setup_sysctl(sc); + return SUCCESS; -fail_start_aen: +attach_fail_ocr_thread: + if (sc->ocr_thread_active) + wakeup(&sc->ocr_chan); attach_fail_irq: mrsas_teardown_intr(sc); attach_fail_cam: @@ -942,10 +932,7 @@ attach_fail_fw: mtx_destroy(&sc->mpt_cmd_pool_lock); mtx_destroy(&sc->mfi_cmd_pool_lock); mtx_destroy(&sc->raidmap_lock); - /* Destroy the counting semaphore created for Ioctl */ - sema_destroy(&sc->ioctl_count_sema); attach_fail: - destroy_dev(sc->mrsas_cdev); if (sc->reg_res) { bus_release_resource(sc->mrsas_dev, SYS_RES_MEMORY, sc->reg_res_id, sc->reg_res); @@ -954,6 +941,63 @@ attach_fail: } /* + * Interrupt config hook + */ +static void +mrsas_ich_startup(void *arg) +{ + struct mrsas_softc *sc = (struct mrsas_softc *)arg; + + /* + * Intialize a counting Semaphore to take care no. of concurrent IOCTLs + */ + sema_init(&sc->ioctl_count_sema, + MRSAS_MAX_MFI_CMDS - 5, + IOCTL_SEMA_DESCRIPTION); + + /* Create a /dev entry for mrsas controller. */ + sc->mrsas_cdev = make_dev(&mrsas_cdevsw, device_get_unit(sc->mrsas_dev), UID_ROOT, + GID_OPERATOR, (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP), "mrsas%u", + device_get_unit(sc->mrsas_dev)); + + if (device_get_unit(sc->mrsas_dev) == 0) { + make_dev_alias_p(MAKEDEV_CHECKNAME, + &sc->mrsas_linux_emulator_cdev, sc->mrsas_cdev, + "megaraid_sas_ioctl_node"); + } + if (sc->mrsas_cdev) + sc->mrsas_cdev->si_drv1 = sc; + + /* + * Add this controller to mrsas_mgmt_info structure so that it can be + * exported to management applications + */ + if (device_get_unit(sc->mrsas_dev) == 0) + memset(&mrsas_mgmt_info, 0, sizeof(mrsas_mgmt_info)); + + mrsas_mgmt_info.count++; + mrsas_mgmt_info.sc_ptr[mrsas_mgmt_info.max_index] = sc; + mrsas_mgmt_info.max_index++; + + /* Enable Interrupts */ + mrsas_enable_intr(sc); + + /* Initiate AEN (Asynchronous Event Notification) */ + if (mrsas_start_aen(sc)) { + device_printf(sc->mrsas_dev, "Error: AEN registration FAILED !!! " + "Further events from the controller will not be communicated.\n" + "Either there is some problem in the controller" + "or the controller does not support AEN.\n" + "Please contact to the SUPPORT TEAM if the problem persists\n"); + } + if (sc->mrsas_ich.ich_arg != NULL) { + device_printf(sc->mrsas_dev, "Disestablish mrsas intr hook\n"); + config_intrhook_disestablish(&sc->mrsas_ich); + sc->mrsas_ich.ich_arg = NULL; + } +} + +/* * mrsas_detach: De-allocates and teardown resources * input: pointer to device struct * @@ -971,6 +1015,8 @@ mrsas_detach(device_t dev) sc->remove_in_progress = 1; /* Destroy the character device so no other IOCTL will be handled */ + if ((device_get_unit(dev) == 0) && sc->mrsas_linux_emulator_cdev) + destroy_dev(sc->mrsas_linux_emulator_cdev); destroy_dev(sc->mrsas_cdev); /* @@ -991,7 +1037,7 @@ mrsas_detach(device_t dev) i++; if (!(i % MRSAS_RESET_NOTICE_INTERVAL)) { mrsas_dprint(sc, MRSAS_INFO, - "[%2d]waiting for ocr to be finished\n", i); + "[%2d]waiting for OCR to be finished from %s\n", i, __func__); } pause("mr_shutdown", hz); } @@ -1067,7 +1113,14 @@ mrsas_free_mem(struct mrsas_softc *sc) if (sc->ld_drv_map[i] != NULL) free(sc->ld_drv_map[i], M_MRSAS); } - + for (i = 0; i < 2; i++) { + if (sc->jbodmap_phys_addr[i]) + bus_dmamap_unload(sc->jbodmap_tag[i], sc->jbodmap_dmamap[i]); + if (sc->jbodmap_mem[i] != NULL) + bus_dmamem_free(sc->jbodmap_tag[i], sc->jbodmap_mem[i], sc->jbodmap_dmamap[i]); + if (sc->jbodmap_tag[i] != NULL) + bus_dma_tag_destroy(sc->jbodmap_tag[i]); + } /* * Free version buffer memroy */ @@ -1229,9 +1282,7 @@ mrsas_teardown_intr(struct mrsas_softc *sc) static int mrsas_suspend(device_t dev) { - struct mrsas_softc *sc; - - sc = device_get_softc(dev); + /* This will be filled when the driver will have hibernation support */ return (0); } @@ -1244,9 +1295,7 @@ mrsas_suspend(device_t dev) static int mrsas_resume(device_t dev) { - struct mrsas_softc *sc; - - sc = device_get_softc(dev); + /* This will be filled when the driver will have hibernation support */ return (0); } @@ -1317,9 +1366,7 @@ mrsas_ioctl(struct cdev *dev, u_long cmd, caddr_t arg, int flag, d_thread_t *td) i++; if (!(i % MRSAS_RESET_NOTICE_INTERVAL)) { mrsas_dprint(sc, MRSAS_INFO, - "[%2d]waiting for " - "OCR to be finished %d\n", i, - sc->ocr_thread_active); + "[%2d]waiting for OCR to be finished from %s\n", i, __func__); } pause("mr_ioctl", hz); } @@ -1483,7 +1530,7 @@ mrsas_isr(void *arg) * perform the appropriate action. Before we return, we clear the response * interrupt. */ -static int +int mrsas_complete_cmd(struct mrsas_softc *sc, u_int32_t MSIxIndex) { Mpi2ReplyDescriptorsUnion_t *desc; @@ -1580,7 +1627,9 @@ mrsas_complete_cmd(struct mrsas_softc *sc, u_int32_t MSIxIndex) if (threshold_reply_count >= THRESHOLD_REPLY_COUNT) { if (sc->msix_enable) { if ((sc->device_id == MRSAS_INVADER) || - (sc->device_id == MRSAS_FURY)) + (sc->device_id == MRSAS_FURY) || + (sc->device_id == MRSAS_INTRUDER) || + (sc->device_id == MRSAS_INTRUDER_24)) mrsas_write_reg(sc, sc->msix_reg_offset[MSIxIndex / 8], ((MSIxIndex & 0x7) << 24) | sc->last_reply_idx[MSIxIndex]); @@ -1602,7 +1651,9 @@ mrsas_complete_cmd(struct mrsas_softc *sc, u_int32_t MSIxIndex) /* Clear response interrupt */ if (sc->msix_enable) { if ((sc->device_id == MRSAS_INVADER) || - (sc->device_id == MRSAS_FURY)) { + (sc->device_id == MRSAS_FURY) || + (sc->device_id == MRSAS_INTRUDER) || + (sc->device_id == MRSAS_INTRUDER_24)) { mrsas_write_reg(sc, sc->msix_reg_offset[MSIxIndex / 8], ((MSIxIndex & 0x7) << 24) | sc->last_reply_idx[MSIxIndex]); @@ -1686,9 +1737,9 @@ mrsas_alloc_mem(struct mrsas_softc *sc) BUS_SPACE_MAXADDR, /* lowaddr */ BUS_SPACE_MAXADDR, /* highaddr */ NULL, NULL, /* filter, filterarg */ - MRSAS_MAX_IO_SIZE, /* maxsize */ - MRSAS_MAX_SGL, /* nsegments */ - MRSAS_MAX_IO_SIZE, /* maxsegsize */ + MAXPHYS, /* maxsize */ + sc->max_num_sge, /* nsegments */ + MAXPHYS, /* maxsegsize */ 0, /* flags */ NULL, NULL, /* lockfunc, lockarg */ &sc->mrsas_parent_tag /* tag */ @@ -1885,9 +1936,9 @@ mrsas_alloc_mem(struct mrsas_softc *sc) BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, NULL, NULL, - MRSAS_MAX_IO_SIZE, - MRSAS_MAX_SGL, - MRSAS_MAX_IO_SIZE, + MAXPHYS, + sc->max_num_sge, /* nsegments */ + MAXPHYS, BUS_DMA_ALLOCNOW, busdma_lock_mutex, &sc->io_lock, @@ -1989,6 +2040,78 @@ ABORT: return (1); } +/** + * megasas_setup_jbod_map - setup jbod map for FP seq_number. + * @sc: Adapter soft state + * + * Return 0 on success. + */ +void +megasas_setup_jbod_map(struct mrsas_softc *sc) +{ + int i; + uint32_t pd_seq_map_sz; + + pd_seq_map_sz = sizeof(struct MR_PD_CFG_SEQ_NUM_SYNC) + + (sizeof(struct MR_PD_CFG_SEQ) * (MAX_PHYSICAL_DEVICES - 1)); + + if (!sc->ctrl_info->adapterOperations3.useSeqNumJbodFP) { + sc->use_seqnum_jbod_fp = 0; + return; + } + if (sc->jbodmap_mem[0]) + goto skip_alloc; + + for (i = 0; i < 2; i++) { + if (bus_dma_tag_create(sc->mrsas_parent_tag, + 4, 0, + BUS_SPACE_MAXADDR_32BIT, + BUS_SPACE_MAXADDR, + NULL, NULL, + pd_seq_map_sz, + 1, + pd_seq_map_sz, + BUS_DMA_ALLOCNOW, + NULL, NULL, + &sc->jbodmap_tag[i])) { + device_printf(sc->mrsas_dev, + "Cannot allocate jbod map tag.\n"); + return; + } + if (bus_dmamem_alloc(sc->jbodmap_tag[i], + (void **)&sc->jbodmap_mem[i], + BUS_DMA_NOWAIT, &sc->jbodmap_dmamap[i])) { + device_printf(sc->mrsas_dev, + "Cannot allocate jbod map memory.\n"); + return; + } + bzero(sc->jbodmap_mem[i], pd_seq_map_sz); + + if (bus_dmamap_load(sc->jbodmap_tag[i], sc->jbodmap_dmamap[i], + sc->jbodmap_mem[i], pd_seq_map_sz, + mrsas_addr_cb, &sc->jbodmap_phys_addr[i], + BUS_DMA_NOWAIT)) { + device_printf(sc->mrsas_dev, "Cannot load jbod map memory.\n"); + return; + } + if (!sc->jbodmap_mem[i]) { + device_printf(sc->mrsas_dev, + "Cannot allocate memory for jbod map.\n"); + sc->use_seqnum_jbod_fp = 0; + return; + } + } + +skip_alloc: + if (!megasas_sync_pd_seq_num(sc, false) && + !megasas_sync_pd_seq_num(sc, true)) + sc->use_seqnum_jbod_fp = 1; + else + sc->use_seqnum_jbod_fp = 0; + + device_printf(sc->mrsas_dev, "Jbod map is supported\n"); +} + /* * mrsas_init_fw: Initialize Firmware * input: Adapter soft state @@ -2088,18 +2211,28 @@ mrsas_init_fw(struct mrsas_softc *sc) if (sc->secure_jbod_support) device_printf(sc->mrsas_dev, "FW supports SED \n"); + if (sc->use_seqnum_jbod_fp) + device_printf(sc->mrsas_dev, "FW supports JBOD Map \n"); + if (mrsas_setup_raidmap(sc) != SUCCESS) { - device_printf(sc->mrsas_dev, "Set up RAID map failed.\n"); - return (1); + device_printf(sc->mrsas_dev, "Error: RAID map setup FAILED !!! " + "There seems to be some problem in the controller\n" + "Please contact to the SUPPORT TEAM if the problem persists\n"); } + megasas_setup_jbod_map(sc); + /* For pass-thru, get PD/LD list and controller info */ memset(sc->pd_list, 0, MRSAS_MAX_PD * sizeof(struct mrsas_pd_list)); - mrsas_get_pd_list(sc); - + if (mrsas_get_pd_list(sc) != SUCCESS) { + device_printf(sc->mrsas_dev, "Get PD list failed.\n"); + return (1); + } memset(sc->ld_ids, 0xff, MRSAS_MAX_LD_IDS); - mrsas_get_ld_list(sc); - + if (mrsas_get_ld_list(sc) != SUCCESS) { + device_printf(sc->mrsas_dev, "Get LD lsit failed.\n"); + return (1); + } /* * Compute the max allowed sectors per IO: The controller info has * two limits on max sectors. Driver should use the minimum of these @@ -2149,7 +2282,7 @@ int mrsas_init_adapter(struct mrsas_softc *sc) { uint32_t status; - u_int32_t max_cmd; + u_int32_t max_cmd, scratch_pad_2; int ret; int i = 0; @@ -2168,13 +2301,33 @@ mrsas_init_adapter(struct mrsas_softc *sc) 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)); - sc->chain_frames_alloc_sz = 1024 * max_cmd; + scratch_pad_2 = mrsas_read_reg(sc, offsetof(mrsas_reg_set, + outbound_scratch_pad_2)); + /* + * If scratch_pad_2 & MEGASAS_MAX_CHAIN_SIZE_UNITS_MASK is set, + * Firmware support extended IO chain frame which is 4 time more + * than legacy Firmware. Legacy Firmware - Frame size is (8 * 128) = + * 1K 1M IO Firmware - Frame size is (8 * 128 * 4) = 4K + */ + if (scratch_pad_2 & MEGASAS_MAX_CHAIN_SIZE_UNITS_MASK) + sc->max_chain_frame_sz = + ((scratch_pad_2 & MEGASAS_MAX_CHAIN_SIZE_MASK) >> 5) + * MEGASAS_1MB_IO; + else + sc->max_chain_frame_sz = + ((scratch_pad_2 & MEGASAS_MAX_CHAIN_SIZE_MASK) >> 5) + * MEGASAS_256K_IO; + + sc->chain_frames_alloc_sz = sc->max_chain_frame_sz * max_cmd; sc->max_sge_in_main_msg = (MRSAS_MPI2_RAID_DEFAULT_IO_FRAME_SIZE - offsetof(MRSAS_RAID_SCSI_IO_REQUEST, SGL)) / 16; - sc->max_sge_in_chain = MRSAS_MAX_SZ_CHAIN_FRAME / sizeof(MPI2_SGE_IO_UNION); + sc->max_sge_in_chain = sc->max_chain_frame_sz / sizeof(MPI2_SGE_IO_UNION); sc->max_num_sge = sc->max_sge_in_main_msg + sc->max_sge_in_chain - 2; + mrsas_dprint(sc, MRSAS_INFO, "Avago Debug: MAX sge 0x%X MAX chain frame size 0x%X \n", + sc->max_num_sge, sc->max_chain_frame_sz); + /* Used for pass thru MFI frame (DCMD) */ sc->chain_offset_mfi_pthru = offsetof(MRSAS_RAID_SCSI_IO_REQUEST, SGL) / 16; @@ -2299,7 +2452,9 @@ mrsas_ioc_init(struct mrsas_softc *sc) /* driver support Extended MSIX */ if ((sc->device_id == MRSAS_INVADER) || - (sc->device_id == MRSAS_FURY)) { + (sc->device_id == MRSAS_FURY) || + (sc->device_id == MRSAS_INTRUDER) || + (sc->device_id == MRSAS_INTRUDER_24)) { init_frame->driver_operations. mfi_capabilities.support_additional_msix = 1; } @@ -2312,6 +2467,8 @@ mrsas_ioc_init(struct mrsas_softc *sc) init_frame->driver_operations.mfi_capabilities.support_ndrive_r1_lb = 1; init_frame->driver_operations.mfi_capabilities.support_max_255lds = 1; init_frame->driver_operations.mfi_capabilities.security_protocol_cmds_fw = 1; + if (sc->max_chain_frame_sz > MEGASAS_CHAIN_FRAME_SZ_MIN) + init_frame->driver_operations.mfi_capabilities.support_ext_io_size = 1; phys_addr = (bus_addr_t)sc->ioc_init_phys_mem + 1024; init_frame->queue_info_new_phys_addr_lo = phys_addr; init_frame->data_xfer_len = sizeof(Mpi2IOCInitRequest_t); @@ -2414,7 +2571,7 @@ mrsas_alloc_mpt_cmds(struct mrsas_softc *sc) for (i = 0; i < max_cmd; i++) { cmd = sc->mpt_cmd_list[i]; offset = MRSAS_MPI2_RAID_DEFAULT_IO_FRAME_SIZE * i; - chain_offset = 1024 * i; + chain_offset = sc->max_chain_frame_sz * i; sense_offset = MRSAS_SENSE_LEN * i; memset(cmd, 0, sizeof(struct mrsas_mpt_cmd)); cmd->index = i + 1; @@ -2625,16 +2782,20 @@ mrsas_ocr_thread(void *arg) /* Sleep for 1 second and check the queue status */ msleep(&sc->ocr_chan, &sc->sim_lock, PRIBIO, "mrsas_ocr", sc->mrsas_fw_fault_check_delay * hz); - if (sc->remove_in_progress) { + if (sc->remove_in_progress || + sc->adprecovery == MRSAS_HW_CRITICAL_ERROR) { mrsas_dprint(sc, MRSAS_OCR, - "Exit due to shutdown from %s\n", __func__); + "Exit due to %s from %s\n", + sc->remove_in_progress ? "Shutdown" : + "Hardware critical error", __func__); break; } fw_status = mrsas_read_reg(sc, offsetof(mrsas_reg_set, outbound_scratch_pad)); fw_state = fw_status & MFI_STATE_MASK; if (fw_state == MFI_STATE_FAULT || sc->do_timedout_reset) { - device_printf(sc->mrsas_dev, "OCR started due to %s!\n", + device_printf(sc->mrsas_dev, "%s started due to %s!\n", + sc->disableOnlineCtrlReset ? "Kill Adapter" : "OCR", sc->do_timedout_reset ? "IO Timeout" : "FW fault detected"); mtx_lock_spin(&sc->ioctl_lock); @@ -2642,7 +2803,7 @@ mrsas_ocr_thread(void *arg) sc->reset_count++; mtx_unlock_spin(&sc->ioctl_lock); mrsas_xpt_freeze(sc); - mrsas_reset_ctrl(sc); + mrsas_reset_ctrl(sc, sc->do_timedout_reset); mrsas_xpt_release(sc); sc->reset_in_progress = 0; sc->do_timedout_reset = 0; @@ -2689,14 +2850,14 @@ mrsas_reset_reply_desc(struct mrsas_softc *sc) * OCR, Re-fire Managment command and move Controller to Operation state. */ int -mrsas_reset_ctrl(struct mrsas_softc *sc) +mrsas_reset_ctrl(struct mrsas_softc *sc, u_int8_t reset_reason) { int retval = SUCCESS, i, j, retry = 0; u_int32_t host_diag, abs_state, status_reg, reset_adapter; union ccb *ccb; struct mrsas_mfi_cmd *mfi_cmd; struct mrsas_mpt_cmd *mpt_cmd; - MRSAS_REQUEST_DESCRIPTOR_UNION *req_desc; + union mrsas_evt_class_locale class_locale; if (sc->adprecovery == MRSAS_HW_CRITICAL_ERROR) { device_printf(sc->mrsas_dev, @@ -2706,10 +2867,11 @@ mrsas_reset_ctrl(struct mrsas_softc *sc) mrsas_set_bit(MRSAS_FUSION_IN_RESET, &sc->reset_flags); sc->adprecovery = MRSAS_ADPRESET_SM_INFAULT; mrsas_disable_intr(sc); - DELAY(1000 * 1000); + msleep(&sc->ocr_chan, &sc->sim_lock, PRIBIO, "mrsas_ocr", + sc->mrsas_fw_fault_check_delay * hz); /* First try waiting for commands to complete */ - if (mrsas_wait_for_outstanding(sc)) { + if (mrsas_wait_for_outstanding(sc, reset_reason)) { mrsas_dprint(sc, MRSAS_OCR, "resetting adapter from %s.\n", __func__); @@ -2819,31 +2981,17 @@ mrsas_reset_ctrl(struct mrsas_softc *sc) mrsas_dprint(sc, MRSAS_OCR, "mrsas_ioc_init() failed!\n"); continue; } - /* Re-fire management commands */ for (j = 0; j < sc->max_fw_cmds; j++) { mpt_cmd = sc->mpt_cmd_list[j]; if (mpt_cmd->sync_cmd_idx != (u_int32_t)MRSAS_ULONG_MAX) { mfi_cmd = sc->mfi_cmd_list[mpt_cmd->sync_cmd_idx]; - if (mfi_cmd->frame->dcmd.opcode == - MR_DCMD_LD_MAP_GET_INFO) { - mrsas_release_mfi_cmd(mfi_cmd); - mrsas_release_mpt_cmd(mpt_cmd); - } else { - req_desc = mrsas_get_request_desc(sc, - mfi_cmd->cmd_id.context.smid - 1); - mrsas_dprint(sc, MRSAS_OCR, - "Re-fire command DCMD opcode 0x%x index %d\n ", - mfi_cmd->frame->dcmd.opcode, j); - if (!req_desc) - device_printf(sc->mrsas_dev, - "Cannot build MPT cmd.\n"); - else - mrsas_fire_cmd(sc, req_desc->addr.u.low, - req_desc->addr.u.high); - } + mrsas_release_mfi_cmd(mfi_cmd); + mrsas_release_mpt_cmd(mpt_cmd); } } + sc->aen_cmd = NULL; + /* Reset load balance info */ memset(sc->load_balance_info, 0, sizeof(LD_LOAD_BALANCE_INFO) * MAX_LOGICAL_DRIVES_EXT); @@ -2856,10 +3004,37 @@ mrsas_reset_ctrl(struct mrsas_softc *sc) if (!mrsas_get_map_info(sc)) mrsas_sync_map_info(sc); + megasas_setup_jbod_map(sc); + + memset(sc->pd_list, 0, + MRSAS_MAX_PD * sizeof(struct mrsas_pd_list)); + if (mrsas_get_pd_list(sc) != SUCCESS) { + device_printf(sc->mrsas_dev, "Get PD list failed from OCR.\n" + "Will get the latest PD LIST after OCR on event.\n"); + } + memset(sc->ld_ids, 0xff, MRSAS_MAX_LD_IDS); + if (mrsas_get_ld_list(sc) != SUCCESS) { + device_printf(sc->mrsas_dev, "Get LD lsit failed from OCR.\n" + "Will get the latest LD LIST after OCR on event.\n"); + } mrsas_clear_bit(MRSAS_FUSION_IN_RESET, &sc->reset_flags); mrsas_enable_intr(sc); sc->adprecovery = MRSAS_HBA_OPERATIONAL; + /* Register AEN with FW for last sequence number */ + class_locale.members.reserved = 0; + class_locale.members.locale = MR_EVT_LOCALE_ALL; + class_locale.members.class = MR_EVT_CLASS_DEBUG; + + if (mrsas_register_aen(sc, sc->last_seq_num, + class_locale.word)) { + device_printf(sc->mrsas_dev, + "ERROR: AEN registration FAILED from OCR !!! " + "Further events from the controller cannot be notified." + "Either there is some problem in the controller" + "or the controller does not support AEN.\n" + "Please contact to the SUPPORT TEAM if the problem persists\n"); + } /* Adapter reset completed successfully */ device_printf(sc->mrsas_dev, "Reset successful\n"); retval = SUCCESS; @@ -2891,7 +3066,7 @@ void mrsas_kill_hba(struct mrsas_softc *sc) { sc->adprecovery = MRSAS_HW_CRITICAL_ERROR; - pause("mrsas_kill_hba", 1000); + DELAY(1000 * 1000); mrsas_dprint(sc, MRSAS_OCR, "%s\n", __func__); mrsas_write_reg(sc, offsetof(mrsas_reg_set, doorbell), MFI_STOP_ADP); @@ -2937,7 +3112,7 @@ mrsas_complete_outstanding_ioctls(struct mrsas_softc *sc) * completed. */ int -mrsas_wait_for_outstanding(struct mrsas_softc *sc) +mrsas_wait_for_outstanding(struct mrsas_softc *sc, u_int8_t check_reason) { int i, outstanding, retval = 0; u_int32_t fw_state, count, MSIxIndex; @@ -2959,6 +3134,12 @@ mrsas_wait_for_outstanding(struct mrsas_softc *sc) retval = 1; goto out; } + if (check_reason == MFI_DCMD_TIMEOUT_OCR) { + mrsas_dprint(sc, MRSAS_OCR, + "DCMD IO TIMEOUT detected, will reset adapter.\n"); + retval = 1; + goto out; + } outstanding = mrsas_atomic_read(&sc->fw_outstanding); if (!outstanding) goto out; @@ -3016,6 +3197,7 @@ static int mrsas_get_ctrl_info(struct mrsas_softc *sc) { int retcode = 0; + u_int8_t do_ocr = 1; struct mrsas_mfi_cmd *cmd; struct mrsas_dcmd_frame *dcmd; @@ -3045,15 +3227,26 @@ mrsas_get_ctrl_info(struct mrsas_softc *sc) dcmd->sgl.sge32[0].phys_addr = sc->ctlr_info_phys_addr; dcmd->sgl.sge32[0].length = sizeof(struct mrsas_ctrl_info); - if (!mrsas_issue_polled(sc, cmd)) - memcpy(sc->ctrl_info, sc->ctlr_info_mem, sizeof(struct mrsas_ctrl_info)); + retcode = mrsas_issue_polled(sc, cmd); + if (retcode == ETIMEDOUT) + goto dcmd_timeout; else - retcode = 1; + memcpy(sc->ctrl_info, sc->ctlr_info_mem, sizeof(struct mrsas_ctrl_info)); + do_ocr = 0; mrsas_update_ext_vd_details(sc); + sc->use_seqnum_jbod_fp = + sc->ctrl_info->adapterOperations3.useSeqNumJbodFP; + +dcmd_timeout: mrsas_free_ctlr_info_cmd(sc); - mrsas_release_mfi_cmd(cmd); + + if (do_ocr) + sc->do_timedout_reset = MFI_DCMD_TIMEOUT_OCR; + else + mrsas_release_mfi_cmd(cmd); + return (retcode); } @@ -3172,7 +3365,7 @@ mrsas_issue_polled(struct mrsas_softc *sc, struct mrsas_mfi_cmd *cmd) { struct mrsas_header *frame_hdr = &cmd->frame->hdr; u_int8_t max_wait = MRSAS_INTERNAL_CMD_WAIT_TIME; - int i, retcode = 0; + int i, retcode = SUCCESS; frame_hdr->cmd_status = 0xFF; frame_hdr->flags |= MFI_FRAME_DONT_POST_IN_REPLY_QUEUE; @@ -3195,12 +3388,12 @@ mrsas_issue_polled(struct mrsas_softc *sc, struct mrsas_mfi_cmd *cmd) break; } } - if (frame_hdr->cmd_status != 0) { - if (frame_hdr->cmd_status == 0xFF) - device_printf(sc->mrsas_dev, "DCMD timed out after %d seconds.\n", max_wait); - else - device_printf(sc->mrsas_dev, "DCMD failed, status = 0x%x\n", frame_hdr->cmd_status); - retcode = 1; + if (frame_hdr->cmd_status == 0xFF) { + device_printf(sc->mrsas_dev, "DCMD timed out after %d " + "seconds from %s\n", max_wait, __func__); + device_printf(sc->mrsas_dev, "DCMD opcode 0x%X\n", + cmd->frame->dcmd.opcode); + retcode = ETIMEDOUT; } return (retcode); } @@ -3294,7 +3487,10 @@ mrsas_build_mptmfi_passthru(struct mrsas_softc *sc, struct mrsas_mfi_cmd *mfi_cm io_req = mpt_cmd->io_request; - if ((sc->device_id == MRSAS_INVADER) || (sc->device_id == MRSAS_FURY)) { + if ((sc->device_id == MRSAS_INVADER) || + (sc->device_id == MRSAS_FURY) || + (sc->device_id == MRSAS_INTRUDER) || + (sc->device_id == MRSAS_INTRUDER_24)) { pMpi25IeeeSgeChain64_t sgl_ptr_end = (pMpi25IeeeSgeChain64_t)&io_req->SGL; sgl_ptr_end += sc->max_sge_in_main_msg - 1; @@ -3311,7 +3507,7 @@ mrsas_build_mptmfi_passthru(struct mrsas_softc *sc, struct mrsas_mfi_cmd *mfi_cm mpi25_ieee_chain->Flags = IEEE_SGE_FLAGS_CHAIN_ELEMENT | MPI2_IEEE_SGE_FLAGS_IOCPLBNTA_ADDR; - mpi25_ieee_chain->Length = MRSAS_MAX_SZ_CHAIN_FRAME; + mpi25_ieee_chain->Length = sc->max_chain_frame_sz; return (0); } @@ -3329,10 +3525,10 @@ mrsas_issue_blocked_cmd(struct mrsas_softc *sc, struct mrsas_mfi_cmd *cmd) { u_int8_t max_wait = MRSAS_INTERNAL_CMD_WAIT_TIME; unsigned long total_time = 0; - int retcode = 0; + int retcode = SUCCESS; /* Initialize cmd_status */ - cmd->cmd_status = ECONNREFUSED; + cmd->cmd_status = 0xFF; /* Build MPT-MFI command for issue to FW */ if (mrsas_issue_dcmd(sc, cmd)) { @@ -3342,18 +3538,30 @@ mrsas_issue_blocked_cmd(struct mrsas_softc *sc, struct mrsas_mfi_cmd *cmd) sc->chan = (void *)&cmd; while (1) { - if (cmd->cmd_status == ECONNREFUSED) { + if (cmd->cmd_status == 0xFF) { tsleep((void *)&sc->chan, 0, "mrsas_sleep", hz); } else break; - total_time++; - if (total_time >= max_wait) { - device_printf(sc->mrsas_dev, - "Internal command timed out after %d seconds.\n", max_wait); - retcode = 1; - break; + + if (!cmd->sync_cmd) { /* cmd->sync will be set for an IOCTL + * command */ + total_time++; + if (total_time >= max_wait) { + device_printf(sc->mrsas_dev, + "Internal command timed out after %d seconds.\n", max_wait); + retcode = 1; + break; + } } } + + if (cmd->cmd_status == 0xFF) { + device_printf(sc->mrsas_dev, "DCMD timed out after %d " + "seconds from %s\n", max_wait, __func__); + device_printf(sc->mrsas_dev, "DCMD opcode 0x%X\n", + cmd->frame->dcmd.opcode); + retcode = ETIMEDOUT; + } return (retcode); } @@ -3404,6 +3612,7 @@ mrsas_complete_mptmfi_passthru(struct mrsas_softc *sc, struct mrsas_mfi_cmd *cmd (cmd->frame->dcmd.mbox.b[1] == 1)) { sc->fast_path_io = 0; mtx_lock(&sc->raidmap_lock); + sc->map_update_cmd = NULL; if (cmd_status != 0) { if (cmd_status != MFI_STAT_NOT_FOUND) device_printf(sc->mrsas_dev, "map sync failed, status=%x\n", cmd_status); @@ -3427,6 +3636,28 @@ mrsas_complete_mptmfi_passthru(struct mrsas_softc *sc, struct mrsas_mfi_cmd *cmd cmd->frame->dcmd.opcode == MR_DCMD_CTRL_EVENT_GET) { sc->mrsas_aen_triggered = 0; } + /* FW has an updated PD sequence */ + if ((cmd->frame->dcmd.opcode == + MR_DCMD_SYSTEM_PD_MAP_GET_INFO) && + (cmd->frame->dcmd.mbox.b[0] == 1)) { + + mtx_lock(&sc->raidmap_lock); + sc->jbod_seq_cmd = NULL; + mrsas_release_mfi_cmd(cmd); + + if (cmd_status == MFI_STAT_OK) { + sc->pd_seq_map_id++; + /* Re-register a pd sync seq num cmd */ + if (megasas_sync_pd_seq_num(sc, true)) + sc->use_seqnum_jbod_fp = 0; + } else { + sc->use_seqnum_jbod_fp = 0; + device_printf(sc->mrsas_dev, + "Jbod map sync failed, status=%x\n", cmd_status); + } + mtx_unlock(&sc->raidmap_lock); + break; + } /* See if got an event notification */ if (cmd->frame->dcmd.opcode == MR_DCMD_CTRL_EVENT_WAIT) mrsas_complete_aen(sc, cmd); @@ -3458,7 +3689,7 @@ mrsas_wakeup(struct mrsas_softc *sc, struct mrsas_mfi_cmd *cmd) { cmd->cmd_status = cmd->frame->io.cmd_status; - if (cmd->cmd_status == ECONNREFUSED) + if (cmd->cmd_status == 0xFF) cmd->cmd_status = 0; sc->chan = (void *)&cmd; @@ -3489,9 +3720,10 @@ mrsas_shutdown_ctlr(struct mrsas_softc *sc, u_int32_t opcode) } if (sc->aen_cmd) mrsas_issue_blocked_abort_cmd(sc, sc->aen_cmd); - if (sc->map_update_cmd) mrsas_issue_blocked_abort_cmd(sc, sc->map_update_cmd); + if (sc->jbod_seq_cmd) + mrsas_issue_blocked_abort_cmd(sc, sc->jbod_seq_cmd); dcmd = &cmd->frame->dcmd; memset(dcmd->mbox.b, 0, MFI_MBOX_SIZE); @@ -3553,6 +3785,85 @@ mrsas_flush_cache(struct mrsas_softc *sc) return; } +int +megasas_sync_pd_seq_num(struct mrsas_softc *sc, boolean_t pend) +{ + int retcode = 0; + u_int8_t do_ocr = 1; + struct mrsas_mfi_cmd *cmd; + struct mrsas_dcmd_frame *dcmd; + uint32_t pd_seq_map_sz; + struct MR_PD_CFG_SEQ_NUM_SYNC *pd_sync; + bus_addr_t pd_seq_h; + + pd_seq_map_sz = sizeof(struct MR_PD_CFG_SEQ_NUM_SYNC) + + (sizeof(struct MR_PD_CFG_SEQ) * + (MAX_PHYSICAL_DEVICES - 1)); + + cmd = mrsas_get_mfi_cmd(sc); + if (!cmd) { + device_printf(sc->mrsas_dev, + "Cannot alloc for ld map info cmd.\n"); + return 1; + } + dcmd = &cmd->frame->dcmd; + + pd_sync = (void *)sc->jbodmap_mem[(sc->pd_seq_map_id & 1)]; + pd_seq_h = sc->jbodmap_phys_addr[(sc->pd_seq_map_id & 1)]; + if (!pd_sync) { + device_printf(sc->mrsas_dev, + "Failed to alloc mem for jbod map info.\n"); + mrsas_release_mfi_cmd(cmd); + return (ENOMEM); + } + memset(pd_sync, 0, pd_seq_map_sz); + memset(dcmd->mbox.b, 0, MFI_MBOX_SIZE); + dcmd->cmd = MFI_CMD_DCMD; + dcmd->cmd_status = 0xFF; + dcmd->sge_count = 1; + dcmd->timeout = 0; + dcmd->pad_0 = 0; + dcmd->data_xfer_len = (pd_seq_map_sz); + dcmd->opcode = (MR_DCMD_SYSTEM_PD_MAP_GET_INFO); + dcmd->sgl.sge32[0].phys_addr = (pd_seq_h); + dcmd->sgl.sge32[0].length = (pd_seq_map_sz); + + if (pend) { + dcmd->mbox.b[0] = MRSAS_DCMD_MBOX_PEND_FLAG; + dcmd->flags = (MFI_FRAME_DIR_WRITE); + sc->jbod_seq_cmd = cmd; + if (mrsas_issue_dcmd(sc, cmd)) { + device_printf(sc->mrsas_dev, + "Fail to send sync map info command.\n"); + return 1; + } else + return 0; + } else + dcmd->flags = MFI_FRAME_DIR_READ; + + retcode = mrsas_issue_polled(sc, cmd); + if (retcode == ETIMEDOUT) + goto dcmd_timeout; + + if (pd_sync->count > MAX_PHYSICAL_DEVICES) { + device_printf(sc->mrsas_dev, + "driver supports max %d JBOD, but FW reports %d\n", + MAX_PHYSICAL_DEVICES, pd_sync->count); + retcode = -EINVAL; + } + if (!retcode) + sc->pd_seq_map_id++; + do_ocr = 0; + +dcmd_timeout: + if (do_ocr) + sc->do_timedout_reset = MFI_DCMD_TIMEOUT_OCR; + else + mrsas_release_mfi_cmd(cmd); + + return (retcode); +} + /* * mrsas_get_map_info: Load and validate RAID map input: * Adapter instance soft state @@ -3622,14 +3933,11 @@ mrsas_get_ld_map_info(struct mrsas_softc *sc) dcmd->sgl.sge32[0].phys_addr = map_phys_addr; dcmd->sgl.sge32[0].length = sc->current_map_sz; - if (!mrsas_issue_polled(sc, cmd)) - retcode = 0; - else { - device_printf(sc->mrsas_dev, - "Fail to send get LD map info cmd.\n"); - retcode = 1; - } - mrsas_release_mfi_cmd(cmd); + retcode = mrsas_issue_polled(sc, cmd); + if (retcode == ETIMEDOUT) + sc->do_timedout_reset = MFI_DCMD_TIMEOUT_OCR; + else + mrsas_release_mfi_cmd(cmd); return (retcode); } @@ -3714,6 +4022,7 @@ static int mrsas_get_pd_list(struct mrsas_softc *sc) { int retcode = 0, pd_index = 0, pd_count = 0, pd_list_size; + u_int8_t do_ocr = 1; struct mrsas_mfi_cmd *cmd; struct mrsas_dcmd_frame *dcmd; struct MR_PD_LIST *pd_list_mem; @@ -3735,6 +4044,8 @@ mrsas_get_pd_list(struct mrsas_softc *sc) device_printf(sc->mrsas_dev, "Cannot alloc dmamap for get PD list cmd\n"); mrsas_release_mfi_cmd(cmd); + mrsas_free_tmp_dcmd(tcmd); + free(tcmd, M_MRSAS); return (ENOMEM); } else { pd_list_mem = tcmd->tmp_dcmd_mem; @@ -3755,15 +4066,14 @@ mrsas_get_pd_list(struct mrsas_softc *sc) dcmd->sgl.sge32[0].phys_addr = pd_list_phys_addr; dcmd->sgl.sge32[0].length = MRSAS_MAX_PD * sizeof(struct MR_PD_LIST); - if (!mrsas_issue_polled(sc, cmd)) - retcode = 0; - else - retcode = 1; + retcode = mrsas_issue_polled(sc, cmd); + if (retcode == ETIMEDOUT) + goto dcmd_timeout; /* Get the instance PD list */ pd_count = MRSAS_MAX_PD; pd_addr = pd_list_mem->addr; - if (retcode == 0 && pd_list_mem->count < pd_count) { + if (pd_list_mem->count < pd_count) { memset(sc->local_pd_list, 0, MRSAS_MAX_PD * sizeof(struct mrsas_pd_list)); for (pd_index = 0; pd_index < pd_list_mem->count; pd_index++) { @@ -3774,15 +4084,22 @@ mrsas_get_pd_list(struct mrsas_softc *sc) MR_PD_STATE_SYSTEM; pd_addr++; } + /* + * Use mutext/spinlock if pd_list component size increase more than + * 32 bit. + */ + memcpy(sc->pd_list, sc->local_pd_list, sizeof(sc->local_pd_list)); + do_ocr = 0; } - /* - * Use mutext/spinlock if pd_list component size increase more than - * 32 bit. - */ - memcpy(sc->pd_list, sc->local_pd_list, sizeof(sc->local_pd_list)); +dcmd_timeout: mrsas_free_tmp_dcmd(tcmd); - mrsas_release_mfi_cmd(cmd); free(tcmd, M_MRSAS); + + if (do_ocr) + sc->do_timedout_reset = MFI_DCMD_TIMEOUT_OCR; + else + mrsas_release_mfi_cmd(cmd); + return (retcode); } @@ -3798,6 +4115,7 @@ static int mrsas_get_ld_list(struct mrsas_softc *sc) { int ld_list_size, retcode = 0, ld_index = 0, ids = 0; + u_int8_t do_ocr = 1; struct mrsas_mfi_cmd *cmd; struct mrsas_dcmd_frame *dcmd; struct MR_LD_LIST *ld_list_mem; @@ -3818,6 +4136,8 @@ mrsas_get_ld_list(struct mrsas_softc *sc) device_printf(sc->mrsas_dev, "Cannot alloc dmamap for get LD list cmd\n"); mrsas_release_mfi_cmd(cmd); + mrsas_free_tmp_dcmd(tcmd); + free(tcmd, M_MRSAS); return (ENOMEM); } else { ld_list_mem = tcmd->tmp_dcmd_mem; @@ -3839,18 +4159,16 @@ mrsas_get_ld_list(struct mrsas_softc *sc) dcmd->sgl.sge32[0].length = sizeof(struct MR_LD_LIST); dcmd->pad_0 = 0; - if (!mrsas_issue_polled(sc, cmd)) - retcode = 0; - else - retcode = 1; + retcode = mrsas_issue_polled(sc, cmd); + if (retcode == ETIMEDOUT) + goto dcmd_timeout; #if VD_EXT_DEBUG printf("Number of LDs %d\n", ld_list_mem->ldCount); #endif /* Get the instance LD list */ - if ((retcode == 0) && - (ld_list_mem->ldCount <= sc->fw_supported_vd_count)) { + if (ld_list_mem->ldCount <= sc->fw_supported_vd_count) { sc->CurLdCount = ld_list_mem->ldCount; memset(sc->ld_ids, 0xff, MAX_LOGICAL_DRIVES_EXT); for (ld_index = 0; ld_index < ld_list_mem->ldCount; ld_index++) { @@ -3859,10 +4177,17 @@ mrsas_get_ld_list(struct mrsas_softc *sc) sc->ld_ids[ids] = ld_list_mem->ldList[ld_index].ref.ld_context.targetId; } } + do_ocr = 0; } +dcmd_timeout: mrsas_free_tmp_dcmd(tcmd); - mrsas_release_mfi_cmd(cmd); free(tcmd, M_MRSAS); + + if (do_ocr) + sc->do_timedout_reset = MFI_DCMD_TIMEOUT_OCR; + else + mrsas_release_mfi_cmd(cmd); + return (retcode); } @@ -4018,7 +4343,7 @@ mrsas_aen_handler(struct mrsas_softc *sc) union mrsas_evt_class_locale class_locale; int doscan = 0; u_int32_t seq_num; - int error; + int error, fail_aen = 0; if (sc == NULL) { printf("invalid instance!\n"); @@ -4027,13 +4352,19 @@ mrsas_aen_handler(struct mrsas_softc *sc) if (sc->evt_detail_mem) { switch (sc->evt_detail_mem->code) { case MR_EVT_PD_INSERTED: - mrsas_get_pd_list(sc); - mrsas_bus_scan_sim(sc, sc->sim_1); + fail_aen = mrsas_get_pd_list(sc); + if (!fail_aen) + mrsas_bus_scan_sim(sc, sc->sim_1); + else + goto skip_register_aen; doscan = 0; break; case MR_EVT_PD_REMOVED: - mrsas_get_pd_list(sc); - mrsas_bus_scan_sim(sc, sc->sim_1); + fail_aen = mrsas_get_pd_list(sc); + if (!fail_aen) + mrsas_bus_scan_sim(sc, sc->sim_1); + else + goto skip_register_aen; doscan = 0; break; case MR_EVT_LD_OFFLINE: @@ -4043,8 +4374,11 @@ mrsas_aen_handler(struct mrsas_softc *sc) doscan = 0; break; case MR_EVT_LD_CREATED: - mrsas_get_ld_list(sc); - mrsas_bus_scan_sim(sc, sc->sim_0); + fail_aen = mrsas_get_ld_list(sc); + if (!fail_aen) + mrsas_bus_scan_sim(sc, sc->sim_0); + else + goto skip_register_aen; doscan = 0; break; case MR_EVT_CTRL_HOST_BUS_SCAN_REQUESTED: @@ -4061,12 +4395,19 @@ mrsas_aen_handler(struct mrsas_softc *sc) return; } if (doscan) { - mrsas_get_pd_list(sc); - mrsas_dprint(sc, MRSAS_AEN, "scanning ...sim 1\n"); - mrsas_bus_scan_sim(sc, sc->sim_1); - mrsas_get_ld_list(sc); - mrsas_dprint(sc, MRSAS_AEN, "scanning ...sim 0\n"); - mrsas_bus_scan_sim(sc, sc->sim_0); + fail_aen = mrsas_get_pd_list(sc); + if (!fail_aen) { + mrsas_dprint(sc, MRSAS_AEN, "scanning ...sim 1\n"); + mrsas_bus_scan_sim(sc, sc->sim_1); + } else + goto skip_register_aen; + + fail_aen = mrsas_get_ld_list(sc); + if (!fail_aen) { + mrsas_dprint(sc, MRSAS_AEN, "scanning ...sim 0\n"); + mrsas_bus_scan_sim(sc, sc->sim_0); + } else + goto skip_register_aen; } seq_num = sc->evt_detail_mem->seq_num + 1; @@ -4086,6 +4427,9 @@ mrsas_aen_handler(struct mrsas_softc *sc) if (error) device_printf(sc->mrsas_dev, "register aen failed error %x\n", error); +skip_register_aen: + return; + } diff --git a/sys/dev/mrsas/mrsas.h b/sys/dev/mrsas/mrsas.h index 1fa2639..4d19b4f 100644 --- a/sys/dev/mrsas/mrsas.h +++ b/sys/dev/mrsas/mrsas.h @@ -80,6 +80,8 @@ __FBSDID("$FreeBSD$"); #define MRSAS_TBOLT 0x005b #define MRSAS_INVADER 0x005d #define MRSAS_FURY 0x005f +#define MRSAS_INTRUDER 0x00ce +#define MRSAS_INTRUDER_24 0x00cf #define MRSAS_PCI_BAR0 0x10 #define MRSAS_PCI_BAR1 0x14 #define MRSAS_PCI_BAR2 0x1C @@ -102,7 +104,7 @@ __FBSDID("$FreeBSD$"); */ #define BYTE_ALIGNMENT 1 #define MRSAS_MAX_NAME_LENGTH 32 -#define MRSAS_VERSION "06.707.05.00-fbsd" +#define MRSAS_VERSION "06.709.07.00-fbsd" #define MRSAS_ULONG_MAX 0xFFFFFFFFFFFFFFFF #define MRSAS_DEFAULT_TIMEOUT 0x14 /* Temporarily set */ #define DONE 0 @@ -166,7 +168,9 @@ typedef struct _RAID_CONTEXT { u_int8_t numSGE; u_int16_t configSeqNum; u_int8_t spanArm; - u_int8_t resvd2[3]; + u_int8_t priority; /* 0x1D MR_PRIORITY_RANGE */ + u_int8_t numSGEExt; /* 0x1E 1M IO support */ + u_int8_t resvd2; /* 0x1F */ } RAID_CONTEXT; @@ -577,6 +581,7 @@ Mpi2IOCInitRequest_t, MPI2_POINTER pMpi2IOCInitRequest_t; #define MAX_PHYSICAL_DEVICES 256 #define MAX_RAIDMAP_PHYSICAL_DEVICES (MAX_PHYSICAL_DEVICES) #define MR_DCMD_LD_MAP_GET_INFO 0x0300e101 +#define MR_DCMD_SYSTEM_PD_MAP_GET_INFO 0x0200e102 #define MRSAS_MAX_PD_CHANNELS 1 @@ -863,6 +868,22 @@ struct IO_REQUEST_INFO { u_int8_t pd_after_lb; }; +/* + * define MR_PD_CFG_SEQ structure for system PDs + */ +struct MR_PD_CFG_SEQ { + u_int16_t seqNum; + u_int16_t devHandle; + u_int8_t reserved[4]; +} __packed; + +struct MR_PD_CFG_SEQ_NUM_SYNC { + u_int32_t size; + u_int32_t count; + struct MR_PD_CFG_SEQ seq[1]; +} __packed; + + typedef struct _MR_LD_TARGET_SYNC { u_int8_t targetId; u_int8_t reserved; @@ -1223,7 +1244,7 @@ enum MR_EVT_ARGS { /* * Thunderbolt (and later) Defines */ -#define MRSAS_MAX_SZ_CHAIN_FRAME 1024 +#define MEGASAS_CHAIN_FRAME_SZ_MIN 1024 #define MFI_FUSION_ENABLE_INTERRUPT_MASK (0x00000009) #define MRSAS_MPI2_RAID_DEFAULT_IO_FRAME_SIZE 256 #define MRSAS_MPI2_FUNCTION_PASSTHRU_IO_REQUEST 0xF0 @@ -1301,10 +1322,13 @@ typedef enum _REGION_TYPE { #define MRSAS_SCSI_MAX_CMDS 8 #define MRSAS_SCSI_MAX_CDB_LEN 16 #define MRSAS_SCSI_SENSE_BUFFERSIZE 96 -#define MRSAS_MAX_SGL 70 -#define MRSAS_MAX_IO_SIZE (256 * 1024) #define MRSAS_INTERNAL_CMDS 32 +#define MEGASAS_MAX_CHAIN_SIZE_UNITS_MASK 0x400000 +#define MEGASAS_MAX_CHAIN_SIZE_MASK 0x3E0 +#define MEGASAS_256K_IO 128 +#define MEGASAS_1MB_IO (MEGASAS_256K_IO * 4) + /* Request types */ #define MRSAS_REQ_TYPE_INTERNAL_CMD 0x0 #define MRSAS_REQ_TYPE_AEN_FETCH 0x1 @@ -1927,7 +1951,12 @@ struct mrsas_ctrl_info { u_int32_t supportCacheBypassModes:1; u_int32_t supportSecurityonJBOD:1; u_int32_t discardCacheDuringLDDelete:1; - u_int32_t reserved:12; + u_int32_t supportTTYLogCompression:1; + u_int32_t supportCPLDUpdate:1; + u_int32_t supportDiskCacheSettingForSysPDs:1; + u_int32_t supportExtendedSSCSize:1; + u_int32_t useSeqNumJbodFP:1; + u_int32_t reserved:7; } adapterOperations3; u_int8_t pad[0x800 - 0x7EC]; /* 0x7EC */ @@ -2001,7 +2030,9 @@ typedef union _MFI_CAPABILITIES { u_int32_t support_ndrive_r1_lb:1; u_int32_t support_core_affinity:1; u_int32_t security_protocol_cmds_fw:1; - u_int32_t reserved:25; + u_int32_t support_ext_queue_depth:1; + u_int32_t support_ext_io_size:1; + u_int32_t reserved:23; } mfi_capabilities; u_int32_t reg; } MFI_CAPABILITIES; @@ -2435,6 +2466,12 @@ struct mrsas_irq_context { uint32_t MSIxIndex; }; +enum MEGASAS_OCR_REASON { + FW_FAULT_OCR = 0, + SCSIIO_TIMEOUT_OCR = 1, + MFI_DCMD_TIMEOUT_OCR = 2, +}; + /* Controller management info added to support Linux Emulator */ #define MAX_MGMT_ADAPTERS 1024 @@ -2611,6 +2648,8 @@ typedef struct _MRSAS_DRV_PCI_INFORMATION { struct mrsas_softc { device_t mrsas_dev; struct cdev *mrsas_cdev; + struct intr_config_hook mrsas_ich; + struct cdev *mrsas_linux_emulator_cdev; uint16_t device_id; struct resource *reg_res; int reg_res_id; @@ -2669,6 +2708,7 @@ struct mrsas_softc { int msix_enable; uint32_t msix_reg_offset[16]; uint8_t mask_interrupts; + uint16_t max_chain_frame_sz; struct mrsas_mpt_cmd **mpt_cmd_list; struct mrsas_mfi_cmd **mfi_cmd_list; TAILQ_HEAD(, mrsas_mpt_cmd) mrsas_mpt_cmd_list_head; @@ -2691,7 +2731,9 @@ struct mrsas_softc { u_int8_t chain_offset_mfi_pthru; u_int32_t map_sz; u_int64_t map_id; + u_int64_t pd_seq_map_id; struct mrsas_mfi_cmd *map_update_cmd; + struct mrsas_mfi_cmd *jbod_seq_cmd; struct mrsas_mfi_cmd *aen_cmd; u_int8_t fast_path_io; void *chan; @@ -2702,6 +2744,12 @@ struct mrsas_softc { u_int8_t do_timedout_reset; u_int32_t reset_in_progress; u_int32_t reset_count; + + bus_dma_tag_t jbodmap_tag[2]; + bus_dmamap_t jbodmap_dmamap[2]; + void *jbodmap_mem[2]; + bus_addr_t jbodmap_phys_addr[2]; + bus_dma_tag_t raidmap_tag[2]; bus_dmamap_t raidmap_dmamap[2]; void *raidmap_mem[2]; @@ -2745,6 +2793,7 @@ struct mrsas_softc { LD_SPAN_INFO log_to_span[MAX_LOGICAL_DRIVES_EXT]; u_int8_t secure_jbod_support; + u_int8_t use_seqnum_jbod_fp; u_int8_t max256vdSupport; u_int16_t fw_supported_vd_count; u_int16_t fw_supported_pd_count; diff --git a/sys/dev/mrsas/mrsas_cam.c b/sys/dev/mrsas/mrsas_cam.c index 08f9002..18c8196 100644 --- a/sys/dev/mrsas/mrsas_cam.c +++ b/sys/dev/mrsas/mrsas_cam.c @@ -65,11 +65,14 @@ int mrsas_map_request(struct mrsas_softc *sc, struct mrsas_mpt_cmd *cmd, union ccb *ccb); int -mrsas_build_ldio(struct mrsas_softc *sc, struct mrsas_mpt_cmd *cmd, +mrsas_build_ldio_rw(struct mrsas_softc *sc, struct mrsas_mpt_cmd *cmd, union ccb *ccb); int -mrsas_build_dcdb(struct mrsas_softc *sc, struct mrsas_mpt_cmd *cmd, - union ccb *ccb, struct cam_sim *sim); +mrsas_build_ldio_nonrw(struct mrsas_softc *sc, struct mrsas_mpt_cmd *cmd, + union ccb *ccb); +int +mrsas_build_syspdio(struct mrsas_softc *sc, struct mrsas_mpt_cmd *cmd, + union ccb *ccb, struct cam_sim *sim, u_int8_t fp_possible); int mrsas_setup_io(struct mrsas_softc *sc, struct mrsas_mpt_cmd *cmd, union ccb *ccb, u_int32_t device_id, @@ -121,6 +124,7 @@ mrsas_get_updated_dev_handle(struct mrsas_softc *sc, extern u_int8_t megasas_get_best_arm(PLD_LOAD_BALANCE_INFO lbInfo, u_int8_t arm, u_int64_t block, u_int32_t count); +extern int mrsas_complete_cmd(struct mrsas_softc *sc, u_int32_t MSIxIndex); /* @@ -341,7 +345,7 @@ mrsas_action(struct cam_sim *sim, union ccb *ccb) else ccb->cpi.max_target = MRSAS_MAX_LD_IDS - 1; #if (__FreeBSD_version > 704000) - ccb->cpi.maxio = MRSAS_MAX_IO_SIZE; + ccb->cpi.maxio = sc->max_num_sge * MRSAS_PAGE_SIZE; #endif ccb->ccb_h.status = CAM_REQ_CMP; xpt_done(ccb); @@ -392,7 +396,7 @@ mrsas_scsiio_timeout(void *data) callout_reset(&cmd->cm_callout, (600000 * hz) / 1000, mrsas_scsiio_timeout, cmd); #endif - sc->do_timedout_reset = 1; + sc->do_timedout_reset = SCSIIO_TIMEOUT_OCR; if (sc->ocr_thread_active) wakeup(&sc->ocr_chan); } @@ -415,6 +419,7 @@ mrsas_startio(struct mrsas_softc *sc, struct cam_sim *sim, struct ccb_hdr *ccb_h = &(ccb->ccb_h); struct ccb_scsiio *csio = &(ccb->csio); MRSAS_REQUEST_DESCRIPTOR_UNION *req_desc; + u_int8_t cmd_type; if ((csio->cdb_io.cdb_bytes[0]) == SYNCHRONIZE_CACHE) { ccb->ccb_h.status = CAM_REQ_CMP; @@ -458,7 +463,7 @@ mrsas_startio(struct mrsas_softc *sc, struct cam_sim *sim, ccb_h->status = CAM_REQ_INVALID; goto done; case CAM_DATA_VADDR: - if (csio->dxfer_len > MRSAS_MAX_IO_SIZE) { + if (csio->dxfer_len > (sc->max_num_sge * MRSAS_PAGE_SIZE)) { mrsas_release_mpt_cmd(cmd); ccb_h->status = CAM_REQ_TOO_BIG; goto done; @@ -468,6 +473,11 @@ mrsas_startio(struct mrsas_softc *sc, struct cam_sim *sim, cmd->data = csio->data_ptr; break; case CAM_DATA_BIO: + if (csio->dxfer_len > (sc->max_num_sge * MRSAS_PAGE_SIZE)) { + mrsas_release_mpt_cmd(cmd); + ccb_h->status = CAM_REQ_TOO_BIG; + goto done; + } cmd->length = csio->dxfer_len; if (cmd->length) cmd->data = csio->data_ptr; @@ -479,7 +489,7 @@ mrsas_startio(struct mrsas_softc *sc, struct cam_sim *sim, #else if (!(ccb_h->flags & CAM_DATA_PHYS)) { /* Virtual data address */ if (!(ccb_h->flags & CAM_SCATTER_VALID)) { - if (csio->dxfer_len > MRSAS_MAX_IO_SIZE) { + if (csio->dxfer_len > (sc->max_num_sge * MRSAS_PAGE_SIZE)) { mrsas_release_mpt_cmd(cmd); ccb_h->status = CAM_REQ_TOO_BIG; goto done; @@ -517,19 +527,44 @@ mrsas_startio(struct mrsas_softc *sc, struct cam_sim *sim, mtx_lock(&sc->raidmap_lock); /* Check for IO type READ-WRITE targeted for Logical Volume */ - if (mrsas_find_io_type(sim, ccb) == READ_WRITE_LDIO) { + cmd_type = mrsas_find_io_type(sim, ccb); + switch (cmd_type) { + case READ_WRITE_LDIO: /* Build READ-WRITE IO for Logical Volume */ - if (mrsas_build_ldio(sc, cmd, ccb)) { - device_printf(sc->mrsas_dev, "Build LDIO failed.\n"); + if (mrsas_build_ldio_rw(sc, cmd, ccb)) { + device_printf(sc->mrsas_dev, "Build RW LDIO failed.\n"); mtx_unlock(&sc->raidmap_lock); return (1); } - } else { - if (mrsas_build_dcdb(sc, cmd, ccb, sim)) { - device_printf(sc->mrsas_dev, "Build DCDB failed.\n"); + break; + case NON_READ_WRITE_LDIO: + /* Build NON READ-WRITE IO for Logical Volume */ + if (mrsas_build_ldio_nonrw(sc, cmd, ccb)) { + device_printf(sc->mrsas_dev, "Build NON-RW LDIO failed.\n"); mtx_unlock(&sc->raidmap_lock); return (1); } + break; + case READ_WRITE_SYSPDIO: + case NON_READ_WRITE_SYSPDIO: + if (sc->secure_jbod_support && + (cmd_type == NON_READ_WRITE_SYSPDIO)) { + /* Build NON-RW IO for JBOD */ + if (mrsas_build_syspdio(sc, cmd, ccb, sim, 0)) { + device_printf(sc->mrsas_dev, + "Build SYSPDIO failed.\n"); + mtx_unlock(&sc->raidmap_lock); + return (1); + } + } else { + /* Build RW IO for JBOD */ + if (mrsas_build_syspdio(sc, cmd, ccb, sim, 1)) { + device_printf(sc->mrsas_dev, + "Build SYSPDIO failed.\n"); + mtx_unlock(&sc->raidmap_lock); + return (1); + } + } } mtx_unlock(&sc->raidmap_lock); @@ -614,7 +649,10 @@ mrsas_get_mpt_cmd(struct mrsas_softc *sc) if (!TAILQ_EMPTY(&sc->mrsas_mpt_cmd_list_head)) { cmd = TAILQ_FIRST(&sc->mrsas_mpt_cmd_list_head); TAILQ_REMOVE(&sc->mrsas_mpt_cmd_list_head, cmd, next); + } else { + goto out; } + memset((uint8_t *)cmd->io_request, 0, MRSAS_MPI2_RAID_DEFAULT_IO_FRAME_SIZE); cmd->data = NULL; cmd->length = 0; @@ -622,8 +660,9 @@ mrsas_get_mpt_cmd(struct mrsas_softc *sc) cmd->error_code = 0; cmd->load_balance = 0; cmd->ccb_ptr = NULL; - mtx_unlock(&sc->mpt_cmd_pool_lock); +out: + mtx_unlock(&sc->mpt_cmd_pool_lock); return cmd; } @@ -668,7 +707,7 @@ mrsas_get_request_desc(struct mrsas_softc *sc, u_int16_t index) } /* - * mrsas_build_ldio: Builds an LDIO command + * mrsas_build_ldio_rw: Builds an LDIO command * input: Adapter instance soft state * Pointer to command packet * Pointer to CCB @@ -677,7 +716,7 @@ mrsas_get_request_desc(struct mrsas_softc *sc, u_int16_t index) * built successfully, otherwise it returns a 1. */ int -mrsas_build_ldio(struct mrsas_softc *sc, struct mrsas_mpt_cmd *cmd, +mrsas_build_ldio_rw(struct mrsas_softc *sc, struct mrsas_mpt_cmd *cmd, union ccb *ccb) { struct ccb_hdr *ccb_h = &(ccb->ccb_h); @@ -701,12 +740,18 @@ mrsas_build_ldio(struct mrsas_softc *sc, struct mrsas_mpt_cmd *cmd, io_request->DataLength = cmd->length; if (mrsas_map_request(sc, cmd, ccb) == SUCCESS) { - if (cmd->sge_count > MRSAS_MAX_SGL) { + if (cmd->sge_count > sc->max_num_sge) { device_printf(sc->mrsas_dev, "Error: sge_count (0x%x) exceeds" "max (0x%x) allowed\n", cmd->sge_count, sc->max_num_sge); return (FAIL); } + /* + * numSGE store lower 8 bit of sge_count. numSGEExt store + * higher 8 bit of sge_count + */ io_request->RaidContext.numSGE = cmd->sge_count; + io_request->RaidContext.numSGEExt = (uint8_t)(cmd->sge_count >> 8); + } else { device_printf(sc->mrsas_dev, "Data map/load failed.\n"); return (FAIL); @@ -832,7 +877,10 @@ mrsas_setup_io(struct mrsas_softc *sc, struct mrsas_mpt_cmd *cmd, cmd->request_desc->SCSIIO.RequestFlags = (MPI2_REQ_DESCRIPT_FLAGS_HIGH_PRIORITY << MRSAS_REQ_DESCRIPT_FLAGS_TYPE_SHIFT); - if ((sc->device_id == MRSAS_INVADER) || (sc->device_id == MRSAS_FURY)) { + if ((sc->device_id == MRSAS_INVADER) || + (sc->device_id == MRSAS_FURY) || + (sc->device_id == MRSAS_INTRUDER) || + (sc->device_id == MRSAS_INTRUDER_24)) { if (io_request->RaidContext.regLockFlags == REGION_TYPE_UNUSED) cmd->request_desc->SCSIIO.RequestFlags = (MRSAS_REQ_DESCRIPT_FLAGS_NO_LOCK << @@ -861,7 +909,10 @@ mrsas_setup_io(struct mrsas_softc *sc, struct mrsas_mpt_cmd *cmd, cmd->request_desc->SCSIIO.RequestFlags = (MRSAS_REQ_DESCRIPT_FLAGS_LD_IO << MRSAS_REQ_DESCRIPT_FLAGS_TYPE_SHIFT); - if ((sc->device_id == MRSAS_INVADER) || (sc->device_id == MRSAS_FURY)) { + if ((sc->device_id == MRSAS_INVADER) || + (sc->device_id == MRSAS_FURY) || + (sc->device_id == MRSAS_INTRUDER) || + (sc->device_id == MRSAS_INTRUDER_24)) { if (io_request->RaidContext.regLockFlags == REGION_TYPE_UNUSED) cmd->request_desc->SCSIIO.RequestFlags = (MRSAS_REQ_DESCRIPT_FLAGS_NO_LOCK << @@ -879,78 +930,141 @@ mrsas_setup_io(struct mrsas_softc *sc, struct mrsas_mpt_cmd *cmd, } /* - * mrsas_build_dcdb: Builds an DCDB command + * mrsas_build_ldio_nonrw: Builds an LDIO command * input: Adapter instance soft state * Pointer to command packet * Pointer to CCB * - * This function builds the DCDB inquiry command. It returns 0 if the command - * is built successfully, otherwise it returns a 1. + * This function builds the LDIO command packet. It returns 0 if the command is + * built successfully, otherwise it returns a 1. */ int -mrsas_build_dcdb(struct mrsas_softc *sc, struct mrsas_mpt_cmd *cmd, - union ccb *ccb, struct cam_sim *sim) +mrsas_build_ldio_nonrw(struct mrsas_softc *sc, struct mrsas_mpt_cmd *cmd, + union ccb *ccb) { struct ccb_hdr *ccb_h = &(ccb->ccb_h); u_int32_t device_id; - MR_DRV_RAID_MAP_ALL *map_ptr; MRSAS_RAID_SCSI_IO_REQUEST *io_request; io_request = cmd->io_request; device_id = ccb_h->target_id; - map_ptr = sc->ld_drv_map[(sc->map_id & 1)]; - /* - * Check if this is RW for system PD or - * it's a NON RW for sys PD and there is NO secure jbod FW support - */ - if (cam_sim_bus(sim) == 1 && - sc->pd_list[device_id].driveState == MR_PD_STATE_SYSTEM) { + /* FW path for LD Non-RW (SCSI management commands) */ + io_request->Function = MRSAS_MPI2_FUNCTION_LD_IO_REQUEST; + io_request->DevHandle = device_id; + cmd->request_desc->SCSIIO.RequestFlags = + (MPI2_REQ_DESCRIPT_FLAGS_SCSI_IO << + MRSAS_REQ_DESCRIPT_FLAGS_TYPE_SHIFT); - io_request->DevHandle = - map_ptr->raidMap.devHndlInfo[device_id].curDevHdl; - io_request->RaidContext.RAIDFlags = - MR_RAID_FLAGS_IO_SUB_TYPE_SYSTEM_PD << - MR_RAID_CTX_RAID_FLAGS_IO_SUB_TYPE_SHIFT; - cmd->request_desc->SCSIIO.DevHandle = io_request->DevHandle; - cmd->request_desc->SCSIIO.MSIxIndex = - sc->msix_vectors ? smp_processor_id() % sc->msix_vectors : 0; - - if (sc->secure_jbod_support && (mrsas_find_io_type(sim, ccb) == NON_READ_WRITE_SYSPDIO)) { - /* system pd firmware path */ - io_request->Function = MRSAS_MPI2_FUNCTION_LD_IO_REQUEST; - cmd->request_desc->SCSIIO.RequestFlags = - (MPI2_REQ_DESCRIPT_FLAGS_SCSI_IO << MRSAS_REQ_DESCRIPT_FLAGS_TYPE_SHIFT); - } else { - /* system pd fast path */ - io_request->Function = MPI2_FUNCTION_SCSI_IO_REQUEST; - io_request->RaidContext.timeoutValue = map_ptr->raidMap.fpPdIoTimeoutSec; - io_request->RaidContext.regLockFlags = 0; - io_request->RaidContext.regLockRowLBA = 0; - io_request->RaidContext.regLockLength = 0; - - cmd->request_desc->SCSIIO.RequestFlags = - (MPI2_REQ_DESCRIPT_FLAGS_HIGH_PRIORITY << - MRSAS_REQ_DESCRIPT_FLAGS_TYPE_SHIFT); + io_request->RaidContext.VirtualDiskTgtId = device_id; + io_request->LUN[1] = ccb_h->target_lun & 0xF; + io_request->DataLength = cmd->length; - /* - * NOTE - For system pd RW cmds only IoFlags will be FAST_PATH - * Because the NON RW cmds will now go via FW Queue - * and not the Exception queue - */ - if ((sc->device_id == MRSAS_INVADER) || (sc->device_id == MRSAS_FURY)) - io_request->IoFlags |= MPI25_SAS_DEVICE0_FLAGS_ENABLED_FAST_PATH; + if (mrsas_map_request(sc, cmd, ccb) == SUCCESS) { + if (cmd->sge_count > sc->max_num_sge) { + device_printf(sc->mrsas_dev, "Error: sge_count (0x%x) exceeds" + "max (0x%x) allowed\n", cmd->sge_count, sc->max_num_sge); + return (1); } + /* + * numSGE store lower 8 bit of sge_count. numSGEExt store + * higher 8 bit of sge_count + */ + io_request->RaidContext.numSGE = cmd->sge_count; + io_request->RaidContext.numSGEExt = (uint8_t)(cmd->sge_count >> 8); } else { - /* FW path for SysPD or LD Non-RW (SCSI management commands) */ + device_printf(sc->mrsas_dev, "Data map/load failed.\n"); + return (1); + } + return (0); +} + +/* + * mrsas_build_syspdio: Builds an DCDB command + * input: Adapter instance soft state + * Pointer to command packet + * Pointer to CCB + * + * This function builds the DCDB inquiry command. It returns 0 if the command + * is built successfully, otherwise it returns a 1. + */ +int +mrsas_build_syspdio(struct mrsas_softc *sc, struct mrsas_mpt_cmd *cmd, + union ccb *ccb, struct cam_sim *sim, u_int8_t fp_possible) +{ + struct ccb_hdr *ccb_h = &(ccb->ccb_h); + u_int32_t device_id; + MR_DRV_RAID_MAP_ALL *local_map_ptr; + MRSAS_RAID_SCSI_IO_REQUEST *io_request; + struct MR_PD_CFG_SEQ_NUM_SYNC *pd_sync; + + pd_sync = (void *)sc->jbodmap_mem[(sc->pd_seq_map_id - 1) & 1]; + + io_request = cmd->io_request; + device_id = ccb_h->target_id; + local_map_ptr = sc->ld_drv_map[(sc->map_id & 1)]; + io_request->RaidContext.RAIDFlags = MR_RAID_FLAGS_IO_SUB_TYPE_SYSTEM_PD + << MR_RAID_CTX_RAID_FLAGS_IO_SUB_TYPE_SHIFT; + io_request->RaidContext.regLockFlags = 0; + io_request->RaidContext.regLockRowLBA = 0; + io_request->RaidContext.regLockLength = 0; + + /* If FW supports PD sequence number */ + if (sc->use_seqnum_jbod_fp && + sc->pd_list[device_id].driveType == 0x00) { + //printf("Using Drv seq num\n"); + io_request->RaidContext.VirtualDiskTgtId = device_id + 255; + io_request->RaidContext.configSeqNum = pd_sync->seq[device_id].seqNum; + io_request->DevHandle = pd_sync->seq[device_id].devHandle; + io_request->RaidContext.regLockFlags |= + (MR_RL_FLAGS_SEQ_NUM_ENABLE | MR_RL_FLAGS_GRANT_DESTINATION_CUDA); + io_request->RaidContext.Type = MPI2_TYPE_CUDA; + io_request->RaidContext.nseg = 0x1; + } else if (sc->fast_path_io) { + //printf("Using LD RAID map\n"); + io_request->RaidContext.VirtualDiskTgtId = device_id; + io_request->RaidContext.configSeqNum = 0; + local_map_ptr = sc->ld_drv_map[(sc->map_id & 1)]; + io_request->DevHandle = + local_map_ptr->raidMap.devHndlInfo[device_id].curDevHdl; + } else { + //printf("Using FW PATH\n"); + /* Want to send all IO via FW path */ + io_request->RaidContext.VirtualDiskTgtId = device_id; + io_request->RaidContext.configSeqNum = 0; + io_request->DevHandle = 0xFFFF; + } + + cmd->request_desc->SCSIIO.DevHandle = io_request->DevHandle; + cmd->request_desc->SCSIIO.MSIxIndex = + sc->msix_vectors ? smp_processor_id() % sc->msix_vectors : 0; + + if (!fp_possible) { + /* system pd firmware path */ io_request->Function = MRSAS_MPI2_FUNCTION_LD_IO_REQUEST; - io_request->DevHandle = device_id; cmd->request_desc->SCSIIO.RequestFlags = (MPI2_REQ_DESCRIPT_FLAGS_SCSI_IO << MRSAS_REQ_DESCRIPT_FLAGS_TYPE_SHIFT); + io_request->RaidContext.timeoutValue = + local_map_ptr->raidMap.fpPdIoTimeoutSec; + io_request->RaidContext.VirtualDiskTgtId = device_id; + } else { + /* system pd fast path */ + io_request->Function = MPI2_FUNCTION_SCSI_IO_REQUEST; + io_request->RaidContext.timeoutValue = local_map_ptr->raidMap.fpPdIoTimeoutSec; + + /* + * NOTE - For system pd RW cmds only IoFlags will be FAST_PATH + * Because the NON RW cmds will now go via FW Queue + * and not the Exception queue + */ + io_request->IoFlags |= MPI25_SAS_DEVICE0_FLAGS_ENABLED_FAST_PATH; + + cmd->request_desc->SCSIIO.RequestFlags = + (MPI2_REQ_DESCRIPT_FLAGS_HIGH_PRIORITY << + MRSAS_REQ_DESCRIPT_FLAGS_TYPE_SHIFT); } - io_request->RaidContext.VirtualDiskTgtId = device_id; io_request->LUN[1] = ccb_h->target_lun & 0xF; io_request->DataLength = cmd->length; @@ -960,7 +1074,12 @@ mrsas_build_dcdb(struct mrsas_softc *sc, struct mrsas_mpt_cmd *cmd, "max (0x%x) allowed\n", cmd->sge_count, sc->max_num_sge); return (1); } + /* + * numSGE store lower 8 bit of sge_count. numSGEExt store + * higher 8 bit of sge_count + */ io_request->RaidContext.numSGE = cmd->sge_count; + io_request->RaidContext.numSGEExt = (uint8_t)(cmd->sge_count >> 8); } else { device_printf(sc->mrsas_dev, "Data map/load failed.\n"); return (1); @@ -1069,7 +1188,10 @@ mrsas_data_load_cb(void *arg, bus_dma_segment_t *segs, int nseg, int error) io_request = cmd->io_request; sgl_ptr = (pMpi25IeeeSgeChain64_t)&io_request->SGL; - if ((sc->device_id == MRSAS_INVADER) || (sc->device_id == MRSAS_FURY)) { + if ((sc->device_id == MRSAS_INVADER) || + (sc->device_id == MRSAS_FURY) || + (sc->device_id == MRSAS_INTRUDER) || + (sc->device_id == MRSAS_INTRUDER_24)) { pMpi25IeeeSgeChain64_t sgl_ptr_end = sgl_ptr; sgl_ptr_end += sc->max_sge_in_main_msg - 1; @@ -1080,7 +1202,10 @@ mrsas_data_load_cb(void *arg, bus_dma_segment_t *segs, int nseg, int error) sgl_ptr->Address = segs[i].ds_addr; sgl_ptr->Length = segs[i].ds_len; sgl_ptr->Flags = 0; - if ((sc->device_id == MRSAS_INVADER) || (sc->device_id == MRSAS_FURY)) { + if ((sc->device_id == MRSAS_INVADER) || + (sc->device_id == MRSAS_FURY) || + (sc->device_id == MRSAS_INTRUDER) || + (sc->device_id == MRSAS_INTRUDER_24)) { if (i == nseg - 1) sgl_ptr->Flags = IEEE_SGE_FLAGS_END_OF_LIST; } @@ -1090,7 +1215,10 @@ mrsas_data_load_cb(void *arg, bus_dma_segment_t *segs, int nseg, int error) (nseg > sc->max_sge_in_main_msg)) { pMpi25IeeeSgeChain64_t sg_chain; - if ((sc->device_id == MRSAS_INVADER) || (sc->device_id == MRSAS_FURY)) { + if ((sc->device_id == MRSAS_INVADER) || + (sc->device_id == MRSAS_FURY) || + (sc->device_id == MRSAS_INTRUDER) || + (sc->device_id == MRSAS_INTRUDER_24)) { if ((cmd->io_request->IoFlags & MPI25_SAS_DEVICE0_FLAGS_ENABLED_FAST_PATH) != MPI25_SAS_DEVICE0_FLAGS_ENABLED_FAST_PATH) cmd->io_request->ChainOffset = sc->chain_offset_io_request; @@ -1099,7 +1227,10 @@ mrsas_data_load_cb(void *arg, bus_dma_segment_t *segs, int nseg, int error) } else cmd->io_request->ChainOffset = sc->chain_offset_io_request; sg_chain = sgl_ptr; - if ((sc->device_id == MRSAS_INVADER) || (sc->device_id == MRSAS_FURY)) + if ((sc->device_id == MRSAS_INVADER) || + (sc->device_id == MRSAS_FURY) || + (sc->device_id == MRSAS_INTRUDER) || + (sc->device_id == MRSAS_INTRUDER_24)) sg_chain->Flags = IEEE_SGE_FLAGS_CHAIN_ELEMENT; else sg_chain->Flags = (IEEE_SGE_FLAGS_CHAIN_ELEMENT | MPI2_IEEE_SGE_FLAGS_IOCPLBNTA_ADDR); @@ -1170,9 +1301,16 @@ mrsas_cmd_done(struct mrsas_softc *sc, struct mrsas_mpt_cmd *cmd) static void mrsas_cam_poll(struct cam_sim *sim) { + int i; struct mrsas_softc *sc = (struct mrsas_softc *)cam_sim_softc(sim); - mrsas_isr((void *)sc); + if (sc->msix_vectors != 0){ + for (i=0; i<sc->msix_vectors; i++){ + mrsas_complete_cmd(sc, i); + } + } else { + mrsas_complete_cmd(sc, 0); + } } /* diff --git a/sys/dev/mrsas/mrsas_fp.c b/sys/dev/mrsas/mrsas_fp.c index 7ae5662..470b0f7 100644 --- a/sys/dev/mrsas/mrsas_fp.c +++ b/sys/dev/mrsas/mrsas_fp.c @@ -749,7 +749,10 @@ mr_spanset_get_phy_params(struct mrsas_softc *sc, u_int32_t ld, u_int64_t stripR u_int32_t logArm, rowMod, armQ, arm; u_int8_t do_invader = 0; - if ((sc->device_id == MRSAS_INVADER) || (sc->device_id == MRSAS_FURY)) + if ((sc->device_id == MRSAS_INVADER) || + (sc->device_id == MRSAS_FURY) || + (sc->device_id == MRSAS_INTRUDER) || + (sc->device_id == MRSAS_INTRUDER_24)) do_invader = 1; /* Get row and span from io_info for Uneven Span IO. */ @@ -960,7 +963,10 @@ MR_BuildRaidContext(struct mrsas_softc *sc, struct IO_REQUEST_INFO *io_info, regSize += stripSize; } pRAID_Context->timeoutValue = map->raidMap.fpPdIoTimeoutSec; - if ((sc->device_id == MRSAS_INVADER) || (sc->device_id == MRSAS_FURY)) + if ((sc->device_id == MRSAS_INVADER) || + (sc->device_id == MRSAS_FURY) || + (sc->device_id == MRSAS_INTRUDER) || + (sc->device_id == MRSAS_INTRUDER_24)) pRAID_Context->regLockFlags = (isRead) ? raid->regTypeReqOnRead : raid->regTypeReqOnWrite; else pRAID_Context->regLockFlags = (isRead) ? REGION_TYPE_SHARED_READ : raid->regTypeReqOnWrite; @@ -1309,12 +1315,6 @@ mrsas_set_pd_lba(MRSAS_RAID_SCSI_IO_REQUEST * io_request, u_int8_t cdb_len, cdb[3] = (u_int8_t)((start_blk >> 16) & 0xff); cdb[2] = (u_int8_t)((start_blk >> 24) & 0xff); break; - case 12: - cdb[5] = (u_int8_t)(start_blk & 0xff); - cdb[4] = (u_int8_t)((start_blk >> 8) & 0xff); - cdb[3] = (u_int8_t)((start_blk >> 16) & 0xff); - cdb[2] = (u_int8_t)((start_blk >> 24) & 0xff); - break; case 16: cdb[9] = (u_int8_t)(start_blk & 0xff); cdb[8] = (u_int8_t)((start_blk >> 8) & 0xff); @@ -1451,7 +1451,10 @@ MR_GetPhyParams(struct mrsas_softc *sc, u_int32_t ld, u_int32_t rowMod, armQ, arm, logArm; u_int8_t do_invader = 0; - if ((sc->device_id == MRSAS_INVADER) || (sc->device_id == MRSAS_FURY)) + if ((sc->device_id == MRSAS_INVADER) || + (sc->device_id == MRSAS_FURY) || + (sc->device_id == MRSAS_INTRUDER) || + (sc->device_id == MRSAS_INTRUDER_24)) do_invader = 1; row = mega_div64_32(stripRow, raid->rowDataSize); diff --git a/sys/dev/mrsas/mrsas_ioctl.c b/sys/dev/mrsas/mrsas_ioctl.c index 3c4dbf9..4939156 100644 --- a/sys/dev/mrsas/mrsas_ioctl.c +++ b/sys/dev/mrsas/mrsas_ioctl.c @@ -138,6 +138,11 @@ mrsas_passthru(struct mrsas_softc *sc, void *arg, u_long ioctlCmd) kern_sge32 = (struct mrsas_sge32 *) ((unsigned long)cmd->frame + user_ioc->sgl_off); + memset(ioctl_data_tag, 0, (sizeof(bus_dma_tag_t) * MAX_IOCTL_SGE)); + memset(ioctl_data_dmamap, 0, (sizeof(bus_dmamap_t) * MAX_IOCTL_SGE)); + memset(ioctl_data_mem, 0, (sizeof(void *) * MAX_IOCTL_SGE)); + memset(ioctl_data_phys_addr, 0, (sizeof(bus_addr_t) * MAX_IOCTL_SGE)); + /* * For each user buffer, create a mirror buffer and copy in */ @@ -246,7 +251,14 @@ mrsas_passthru(struct mrsas_softc *sc, void *arg, u_long ioctlCmd) * cmd to the SCSI mid-layer */ cmd->sync_cmd = 1; - mrsas_issue_blocked_cmd(sc, cmd); + ret = mrsas_issue_blocked_cmd(sc, cmd); + if (ret == ETIMEDOUT) { + mrsas_dprint(sc, MRSAS_OCR, + "IOCTL command is timed out, initiating OCR\n"); + sc->do_timedout_reset = MFI_DCMD_TIMEOUT_OCR; + ret = EAGAIN; + goto out; + } cmd->sync_cmd = 0; /* @@ -435,6 +447,17 @@ mrsas_create_frame_pool(struct mrsas_softc *sc) device_printf(sc->mrsas_dev, "Cannot alloc MFI frame memory\n"); return (ENOMEM); } + /* + * For MFI controllers. + * max_num_sge = 60 + * max_sge_sz = 16 byte (sizeof megasas_sge_skinny) + * Totl 960 byte (15 MFI frame of 64 byte) + * + * Fusion adapter require only 3 extra frame. + * max_num_sge = 16 (defined as MAX_IOCTL_SGE) + * max_sge_sz = 12 byte (sizeof megasas_sge64) + * Total 192 byte (3 MFI frame of 64 byte) + */ memset(cmd->frame, 0, MRSAS_MFI_FRAME_SIZE); cmd->frame->io.context = cmd->index; cmd->frame->io.pad_0 = 0; |