diff options
-rw-r--r-- | sys/dev/mrsas/mrsas.c | 312 | ||||
-rw-r--r-- | sys/dev/mrsas/mrsas.h | 214 | ||||
-rw-r--r-- | sys/dev/mrsas/mrsas_cam.c | 150 | ||||
-rw-r--r-- | sys/dev/mrsas/mrsas_fp.c | 202 | ||||
-rw-r--r-- | sys/dev/mrsas/mrsas_ioctl.c | 22 | ||||
-rw-r--r-- | sys/dev/mrsas/mrsas_ioctl.h | 6 | ||||
-rw-r--r-- | sys/dev/mrsas/mrsas_linux.c | 5 |
7 files changed, 654 insertions, 257 deletions
diff --git a/sys/dev/mrsas/mrsas.c b/sys/dev/mrsas/mrsas.c index 9c1caa0..3e6dbe8 100644 --- a/sys/dev/mrsas/mrsas.c +++ b/sys/dev/mrsas/mrsas.c @@ -1,6 +1,7 @@ /* + * Copyright (c) 2015, AVAGO Tech. All rights reserved. Author: Marian Choy * Copyright (c) 2014, LSI Corp. All rights reserved. Author: Marian Choy - * Support: freebsdraid@lsi.com + * Support: freebsdraid@avagotech.com * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are @@ -31,7 +32,7 @@ * those of the authors and should not be interpreted as representing * official policies,either expressed or implied, of the FreeBSD Project. * - * Send feedback to: <megaraidfbsd@lsi.com> Mail to: LSI Corporation, 1621 + * Send feedback to: <megaraidfbsd@avagotech.com> Mail to: AVAGO TECHNOLOGIES 1621 * Barber Lane, Milpitas, CA 95035 ATTN: MegaRaid FreeBSD * */ @@ -81,16 +82,19 @@ 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 int mrsas_clear_intr(struct mrsas_softc *sc); -static int -mrsas_get_ctrl_info(struct mrsas_softc *sc, - struct mrsas_ctrl_info *ctrl_info); -static int +static int mrsas_get_ctrl_info(struct mrsas_softc *sc); +static void mrsas_update_ext_vd_details(struct mrsas_softc *sc); +static int mrsas_issue_blocked_abort_cmd(struct mrsas_softc *sc, struct mrsas_mfi_cmd *cmd_to_abort); +static struct mrsas_softc * +mrsas_get_softc_instance(struct cdev *dev, + u_long cmd, caddr_t arg); u_int32_t mrsas_read_reg(struct mrsas_softc *sc, int offset); -u_int8_t +u_int8_t mrsas_build_mptmfi_passthru(struct mrsas_softc *sc, struct mrsas_mfi_cmd *mfi_cmd); +void mrsas_complete_outstanding_ioctls(struct mrsas_softc *sc); int mrsas_transition_to_ready(struct mrsas_softc *sc, int ocr); int mrsas_init_adapter(struct mrsas_softc *sc); int mrsas_alloc_mpt_cmds(struct mrsas_softc *sc); @@ -102,10 +106,10 @@ 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 +int mrsas_issue_blocked_cmd(struct mrsas_softc *sc, struct mrsas_mfi_cmd *cmd); -int +int mrsas_alloc_tmp_dcmd(struct mrsas_softc *sc, struct mrsas_tmp_dcmd *tcmd, int size); void mrsas_release_mfi_cmd(struct mrsas_mfi_cmd *cmd); @@ -122,17 +126,17 @@ void mrsas_teardown_intr(struct mrsas_softc *sc); void mrsas_addr_cb(void *arg, bus_dma_segment_t *segs, int nsegs, int error); void mrsas_kill_hba(struct mrsas_softc *sc); void mrsas_aen_handler(struct mrsas_softc *sc); -void +void mrsas_write_reg(struct mrsas_softc *sc, int offset, u_int32_t value); -void +void mrsas_fire_cmd(struct mrsas_softc *sc, u_int32_t req_desc_lo, u_int32_t req_desc_hi); void mrsas_free_ctlr_info_cmd(struct mrsas_softc *sc); -void +void mrsas_complete_mptmfi_passthru(struct mrsas_softc *sc, struct mrsas_mfi_cmd *cmd, u_int8_t status); -void +void mrsas_map_mpt_cmd_status(struct mrsas_mpt_cmd *cmd, u_int8_t status, u_int8_t extStatus); struct mrsas_mfi_cmd *mrsas_get_mfi_cmd(struct mrsas_softc *sc); @@ -175,9 +179,9 @@ typedef struct mrsas_ident { } MRSAS_CTLR_ID; MRSAS_CTLR_ID device_table[] = { - {0x1000, MRSAS_TBOLT, 0xffff, 0xffff, "LSI Thunderbolt SAS Controller"}, - {0x1000, MRSAS_INVADER, 0xffff, 0xffff, "LSI Invader SAS Controller"}, - {0x1000, MRSAS_FURY, 0xffff, 0xffff, "LSI Fury SAS Controller"}, + {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"}, {0, 0, 0, 0, NULL} }; @@ -272,6 +276,7 @@ mrsas_disable_intr(struct mrsas_softc *sc) u_int32_t mask = 0xFFFFFFFF; u_int32_t status; + sc->mask_interrupts = 1; mrsas_write_reg(sc, offsetof(mrsas_reg_set, outbound_intr_mask), mask); /* Dummy read to force pci flush */ status = mrsas_read_reg(sc, offsetof(mrsas_reg_set, outbound_intr_mask)); @@ -283,6 +288,7 @@ mrsas_enable_intr(struct mrsas_softc *sc) u_int32_t mask = MFI_FUSION_ENABLE_INTERRUPT_MASK; u_int32_t status; + sc->mask_interrupts = 0; mrsas_write_reg(sc, offsetof(mrsas_reg_set, outbound_intr_status), ~0); status = mrsas_read_reg(sc, offsetof(mrsas_reg_set, outbound_intr_status)); @@ -352,7 +358,7 @@ mrsas_probe(device_t dev) if ((id = mrsas_find_ident(dev)) != NULL) { if (first_ctrl) { - printf("LSI MegaRAID SAS FreeBSD mrsas driver version: %s\n", + printf("AVAGO MegaRAID SAS FreeBSD mrsas driver version: %s\n", MRSAS_VERSION); first_ctrl = 0; } @@ -460,6 +466,11 @@ mrsas_get_tunables(struct mrsas_softc *sc) */ TUNABLE_INT_FETCH("hw.mrsas.debug_level", &sc->mrsas_debug); + /* + * Grab the global variables. + */ + TUNABLE_INT_FETCH("hw.mrsas.lb_pending_cmds", &sc->lb_pending_cmds); + /* Grab the unit-instance variables */ snprintf(tmpstr, sizeof(tmpstr), "dev.mrsas.%d.debug_level", device_get_unit(sc->mrsas_dev)); @@ -1163,6 +1174,12 @@ mrsas_free_mem(struct mrsas_softc *sc) */ if (sc->mrsas_parent_tag != NULL) bus_dma_tag_destroy(sc->mrsas_parent_tag); + + /* + * Free ctrl_info memory + */ + if (sc->ctrl_info != NULL) + free(sc->ctrl_info, M_MRSAS); } /* @@ -1231,6 +1248,43 @@ mrsas_resume(device_t dev) return (0); } +/** + * mrsas_get_softc_instance: Find softc instance based on cmd type + * + * This function will return softc instance based on cmd type. + * In some case, application fire ioctl on required management instance and + * do not provide host_no. Use cdev->si_drv1 to get softc instance for those + * case, else get the softc instance from host_no provided by application in + * user data. + */ + +static struct mrsas_softc * +mrsas_get_softc_instance(struct cdev *dev, u_long cmd, caddr_t arg) +{ + struct mrsas_softc *sc = NULL; + struct mrsas_iocpacket *user_ioc = (struct mrsas_iocpacket *)arg; + + if (cmd == MRSAS_IOC_GET_PCI_INFO) { + sc = dev->si_drv1; + } else { + /* + * get the Host number & the softc from data sent by the + * Application + */ + sc = mrsas_mgmt_info.sc_ptr[user_ioc->host_no]; + if ((user_ioc->host_no >= mrsas_mgmt_info.max_index) || (sc == NULL)) { + if (sc == NULL) + mrsas_dprint(sc, MRSAS_FAULT, + "There is no Controller number %d .\n", user_ioc->host_no); + else + mrsas_dprint(sc, MRSAS_FAULT, + "Invalid Controller number %d .\n", user_ioc->host_no); + } + } + + return sc; +} + /* * mrsas_ioctl: IOCtl commands entry point. * @@ -1242,19 +1296,12 @@ mrsas_ioctl(struct cdev *dev, u_long cmd, caddr_t arg, int flag, d_thread_t *td) { struct mrsas_softc *sc; int ret = 0, i = 0; + MRSAS_DRV_PCI_INFORMATION *pciDrvInfo; - struct mrsas_iocpacket *user_ioc = (struct mrsas_iocpacket *)arg; - - /* get the Host number & the softc from data sent by the Application */ - sc = mrsas_mgmt_info.sc_ptr[user_ioc->host_no]; - - if ((mrsas_mgmt_info.max_index == user_ioc->host_no) || (sc == NULL)) { - printf("Please check the controller number\n"); - if (sc == NULL) - printf("There is NO such Host no. %d\n", user_ioc->host_no); - + sc = mrsas_get_softc_instance(dev, cmd, arg); + if (!sc) return ENOENT; - } + if (sc->remove_in_progress) { mrsas_dprint(sc, MRSAS_INFO, "Driver remove or shutdown called.\n"); @@ -1298,6 +1345,22 @@ do_ioctl: case MRSAS_IOC_SCAN_BUS: ret = mrsas_bus_scan(sc); break; + + case MRSAS_IOC_GET_PCI_INFO: + pciDrvInfo = (MRSAS_DRV_PCI_INFORMATION *) arg; + memset(pciDrvInfo, 0, sizeof(MRSAS_DRV_PCI_INFORMATION)); + pciDrvInfo->busNumber = pci_get_bus(sc->mrsas_dev); + pciDrvInfo->deviceNumber = pci_get_slot(sc->mrsas_dev); + pciDrvInfo->functionNumber = pci_get_function(sc->mrsas_dev); + pciDrvInfo->domainID = pci_get_domain(sc->mrsas_dev); + mrsas_dprint(sc, MRSAS_INFO, "pci bus no: %d," + "pci device no: %d, pci function no: %d," + "pci domain ID: %d\n", + pciDrvInfo->busNumber, pciDrvInfo->deviceNumber, + pciDrvInfo->functionNumber, pciDrvInfo->domainID); + ret = 0; + break; + default: mrsas_dprint(sc, MRSAS_TRACE, "IOCTL command 0x%lx is not handled\n", cmd); ret = ENOENT; @@ -1327,8 +1390,10 @@ mrsas_poll(struct cdev *dev, int poll_events, struct thread *td) } if (revents == 0) { if (poll_events & (POLLIN | POLLRDNORM)) { + mtx_lock(&sc->aen_lock); sc->mrsas_poll_waiting = 1; selrecord(td, &sc->mrsas_select); + mtx_unlock(&sc->aen_lock); } } return revents; @@ -1386,6 +1451,9 @@ mrsas_isr(void *arg) struct mrsas_softc *sc = irq_context->sc; int status = 0; + if (sc->mask_interrupts) + return; + if (!sc->msix_vectors) { status = mrsas_clear_intr(sc); if (!status) @@ -1423,7 +1491,7 @@ mrsas_complete_cmd(struct mrsas_softc *sc, u_int32_t MSIxIndex) MRSAS_RAID_SCSI_IO_REQUEST *scsi_io_req; struct mrsas_mpt_cmd *cmd_mpt; struct mrsas_mfi_cmd *cmd_mfi; - u_int8_t arm, reply_descript_type; + u_int8_t reply_descript_type; u_int16_t smid, num_completed; u_int8_t status, extStatus; union desc_value desc_val; @@ -1461,8 +1529,7 @@ mrsas_complete_cmd(struct mrsas_softc *sc, u_int32_t MSIxIndex) device_id = cmd_mpt->ccb_ptr->ccb_h.target_id; lbinfo = &sc->load_balance_info[device_id]; if (cmd_mpt->load_balance == MRSAS_LOAD_BALANCE_FLAG) { - arm = lbinfo->raid1DevHandle[0] == scsi_io_req->DevHandle ? 0 : 1; - mrsas_atomic_dec(&lbinfo->scsi_pending_cmds[arm]); + mrsas_atomic_dec(&lbinfo->scsi_pending_cmds[cmd_mpt->pd_r1_lb]); cmd_mpt->load_balance &= ~MRSAS_LOAD_BALANCE_FLAG; } /* Fall thru and complete IO */ @@ -1607,8 +1674,8 @@ mrsas_map_mpt_cmd_status(struct mrsas_mpt_cmd *cmd, u_int8_t status, u_int8_t ex 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, count; + u_int32_t verbuf_size, io_req_size, reply_desc_size, sense_size, + chain_frame_size, evt_detail_size, count; /* * Allocate parent DMA tag @@ -1860,34 +1927,6 @@ mrsas_setup_raidmap(struct mrsas_softc *sc) { int i; - sc->drv_supported_vd_count = - MRSAS_MAX_LD_CHANNELS * MRSAS_MAX_DEV_PER_CHANNEL; - sc->drv_supported_pd_count = - MRSAS_MAX_PD_CHANNELS * MRSAS_MAX_DEV_PER_CHANNEL; - - if (sc->max256vdSupport) { - sc->fw_supported_vd_count = MAX_LOGICAL_DRIVES_EXT; - sc->fw_supported_pd_count = MAX_PHYSICAL_DEVICES; - } else { - sc->fw_supported_vd_count = MAX_LOGICAL_DRIVES; - sc->fw_supported_pd_count = MAX_PHYSICAL_DEVICES; - } - -#if VD_EXT_DEBUG - device_printf(sc->mrsas_dev, "FW supports: max256vdSupport = %s\n", - sc->max256vdSupport ? "YES" : "NO"); - device_printf(sc->mrsas_dev, "FW supports %dVDs %dPDs\n" - "DRIVER supports %dVDs %dPDs \n", - sc->fw_supported_vd_count, sc->fw_supported_pd_count, - sc->drv_supported_vd_count, sc->drv_supported_pd_count); -#endif - - sc->old_map_sz = sizeof(MR_FW_RAID_MAP) + - (sizeof(MR_LD_SPAN_MAP) * (sc->fw_supported_vd_count - 1)); - sc->new_map_sz = sizeof(MR_FW_RAID_MAP_EXT); - sc->drv_map_sz = sizeof(MR_DRV_RAID_MAP) + - (sizeof(MR_LD_SPAN_MAP) * (sc->drv_supported_vd_count - 1)); - for (i = 0; i < 2; i++) { sc->ld_drv_map[i] = (void *)malloc(sc->drv_map_sz, M_MRSAS, M_NOWAIT); @@ -1902,14 +1941,6 @@ mrsas_setup_raidmap(struct mrsas_softc *sc) } } - sc->max_map_sz = max(sc->old_map_sz, sc->new_map_sz); - - if (sc->max256vdSupport) - sc->current_map_sz = sc->new_map_sz; - else - sc->current_map_sz = sc->old_map_sz; - - for (int i = 0; i < 2; i++) { if (bus_dma_tag_create(sc->mrsas_parent_tag, 4, 0, @@ -1969,7 +2000,7 @@ ABORT: * get_pdlist, get_ld_list and max_sectors are currently not being used, it * is left here as placeholder. */ -static int +static int mrsas_init_fw(struct mrsas_softc *sc) { @@ -1977,7 +2008,6 @@ mrsas_init_fw(struct mrsas_softc *sc) u_int32_t max_sectors_1; u_int32_t max_sectors_2; u_int32_t tmp_sectors; - struct mrsas_ctrl_info *ctrl_info; u_int32_t scratch_pad_2; int msix_enable = 0; int fw_msix_count = 0; @@ -2039,23 +2069,25 @@ mrsas_init_fw(struct mrsas_softc *sc) device_printf(sc->mrsas_dev, "Allocate MFI cmd failed.\n"); return (1); } + sc->ctrl_info = malloc(sizeof(struct mrsas_ctrl_info), M_MRSAS, M_NOWAIT); + if (!sc->ctrl_info) { + device_printf(sc->mrsas_dev, "Malloc for ctrl_info failed.\n"); + return (1); + } /* * Get the controller info from FW, so that the MAX VD support * availability can be decided. */ - ctrl_info = malloc(sizeof(struct mrsas_ctrl_info), M_MRSAS, M_NOWAIT); - if (!ctrl_info) - device_printf(sc->mrsas_dev, "Malloc for ctrl_info failed.\n"); - - if (mrsas_get_ctrl_info(sc, ctrl_info)) { + if (mrsas_get_ctrl_info(sc)) { device_printf(sc->mrsas_dev, "Unable to get FW ctrl_info.\n"); + return (1); } - sc->max256vdSupport = - (u_int8_t)ctrl_info->adapterOperations3.supportMaxExtLDs; + sc->secure_jbod_support = + (u_int8_t)sc->ctrl_info->adapterOperations3.supportSecurityonJBOD; + + if (sc->secure_jbod_support) + device_printf(sc->mrsas_dev, "FW supports SED \n"); - if (ctrl_info->max_lds > 64) { - sc->max256vdSupport = 1; - } if (mrsas_setup_raidmap(sc) != SUCCESS) { device_printf(sc->mrsas_dev, "Set up RAID map failed.\n"); return (1); @@ -2079,9 +2111,9 @@ mrsas_init_fw(struct mrsas_softc *sc) * calculate max_sectors_1. So the number ended up as zero always. */ tmp_sectors = 0; - max_sectors_1 = (1 << ctrl_info->stripe_sz_ops.min) * - ctrl_info->max_strips_per_io; - max_sectors_2 = ctrl_info->max_request_size; + max_sectors_1 = (1 << sc->ctrl_info->stripe_sz_ops.min) * + sc->ctrl_info->max_strips_per_io; + max_sectors_2 = sc->ctrl_info->max_request_size; tmp_sectors = min(max_sectors_1, max_sectors_2); sc->max_sectors_per_req = sc->max_num_sge * MRSAS_PAGE_SIZE / 512; @@ -2089,9 +2121,9 @@ mrsas_init_fw(struct mrsas_softc *sc) sc->max_sectors_per_req = tmp_sectors; sc->disableOnlineCtrlReset = - ctrl_info->properties.OnOffProperties.disableOnlineCtrlReset; + sc->ctrl_info->properties.OnOffProperties.disableOnlineCtrlReset; sc->UnevenSpanSupport = - ctrl_info->adapterOperations2.supportUnevenSpans; + sc->ctrl_info->adapterOperations2.supportUnevenSpans; if (sc->UnevenSpanSupport) { device_printf(sc->mrsas_dev, "FW supports: UnevenSpanSupport=%x\n\n", sc->UnevenSpanSupport); @@ -2101,9 +2133,6 @@ mrsas_init_fw(struct mrsas_softc *sc) else sc->fast_path_io = 0; } - if (ctrl_info) - free(ctrl_info, M_MRSAS); - return (0); } @@ -2135,7 +2164,7 @@ 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 + 1 + 15) / 16 * 16); + sc->reply_q_depth = ((max_cmd + 1 + 15) / 16 * 16) * 2; 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)); @@ -2280,7 +2309,9 @@ mrsas_ioc_init(struct mrsas_softc *sc) init_frame->driver_ver_lo = (bus_addr_t)sc->verbuf_phys_addr; init_frame->driver_ver_hi = 0; } + 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; 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); @@ -2422,7 +2453,7 @@ mrsas_alloc_mpt_cmds(struct mrsas_softc *sc) * This functions fires the command to Firmware by writing to the * inbound_low_queue_port and inbound_high_queue_port. */ -void +void mrsas_fire_cmd(struct mrsas_softc *sc, u_int32_t req_desc_lo, u_int32_t req_desc_hi) { @@ -2702,7 +2733,6 @@ mrsas_reset_ctrl(struct mrsas_softc *sc) /* Reset not supported, kill adapter */ mrsas_dprint(sc, MRSAS_OCR, "Reset not supported, killing adapter.\n"); mrsas_kill_hba(sc); - sc->adprecovery = MRSAS_HW_CRITICAL_ERROR; retval = FAIL; goto out; } @@ -2787,10 +2817,6 @@ mrsas_reset_ctrl(struct mrsas_softc *sc) mrsas_dprint(sc, MRSAS_OCR, "mrsas_ioc_init() failed!\n"); continue; } - mrsas_clear_bit(MRSAS_FUSION_IN_RESET, &sc->reset_flags); - mrsas_enable_intr(sc); - sc->adprecovery = MRSAS_HBA_OPERATIONAL; - /* Re-fire management commands */ for (j = 0; j < sc->max_fw_cmds; j++) { mpt_cmd = sc->mpt_cmd_list[j]; @@ -2820,9 +2846,18 @@ mrsas_reset_ctrl(struct mrsas_softc *sc) memset(sc->load_balance_info, 0, sizeof(LD_LOAD_BALANCE_INFO) * MAX_LOGICAL_DRIVES_EXT); + if (mrsas_get_ctrl_info(sc)) { + mrsas_kill_hba(sc); + retval = FAIL; + goto out; + } if (!mrsas_get_map_info(sc)) mrsas_sync_map_info(sc); + mrsas_clear_bit(MRSAS_FUSION_IN_RESET, &sc->reset_flags); + mrsas_enable_intr(sc); + sc->adprecovery = MRSAS_HBA_OPERATIONAL; + /* Adapter reset completed successfully */ device_printf(sc->mrsas_dev, "Reset successful\n"); retval = SUCCESS; @@ -2853,11 +2888,43 @@ out: void mrsas_kill_hba(struct mrsas_softc *sc) { + sc->adprecovery = MRSAS_HW_CRITICAL_ERROR; + pause("mrsas_kill_hba", 1000); mrsas_dprint(sc, MRSAS_OCR, "%s\n", __func__); mrsas_write_reg(sc, offsetof(mrsas_reg_set, doorbell), MFI_STOP_ADP); /* Flush */ mrsas_read_reg(sc, offsetof(mrsas_reg_set, doorbell)); + mrsas_complete_outstanding_ioctls(sc); +} + +/** + * mrsas_complete_outstanding_ioctls Complete pending IOCTLS after kill_hba + * input: Controller softc + * + * Returns void + */ +void +mrsas_complete_outstanding_ioctls(struct mrsas_softc *sc) +{ + int i; + struct mrsas_mpt_cmd *cmd_mpt; + struct mrsas_mfi_cmd *cmd_mfi; + u_int32_t count, MSIxIndex; + + count = sc->msix_vectors > 0 ? sc->msix_vectors : 1; + for (i = 0; i < sc->max_fw_cmds; i++) { + cmd_mpt = sc->mpt_cmd_list[i]; + + if (cmd_mpt->sync_cmd_idx != (u_int32_t)MRSAS_ULONG_MAX) { + cmd_mfi = sc->mfi_cmd_list[cmd_mpt->sync_cmd_idx]; + if (cmd_mfi->sync_cmd && cmd_mfi->frame->hdr.cmd != MFI_CMD_ABORT) { + for (MSIxIndex = 0; MSIxIndex < count; MSIxIndex++) + mrsas_complete_mptmfi_passthru(sc, cmd_mfi, + cmd_mpt->io_request->RaidContext.status); + } + } + } } /* @@ -2944,8 +3011,7 @@ mrsas_release_mfi_cmd(struct mrsas_mfi_cmd *cmd) * supported by the FW. */ static int -mrsas_get_ctrl_info(struct mrsas_softc *sc, - struct mrsas_ctrl_info *ctrl_info) +mrsas_get_ctrl_info(struct mrsas_softc *sc) { int retcode = 0; struct mrsas_mfi_cmd *cmd; @@ -2978,16 +3044,60 @@ mrsas_get_ctrl_info(struct mrsas_softc *sc, dcmd->sgl.sge32[0].length = sizeof(struct mrsas_ctrl_info); if (!mrsas_issue_polled(sc, cmd)) - memcpy(ctrl_info, sc->ctlr_info_mem, sizeof(struct mrsas_ctrl_info)); + memcpy(sc->ctrl_info, sc->ctlr_info_mem, sizeof(struct mrsas_ctrl_info)); else retcode = 1; + mrsas_update_ext_vd_details(sc); + mrsas_free_ctlr_info_cmd(sc); mrsas_release_mfi_cmd(cmd); return (retcode); } /* + * mrsas_update_ext_vd_details : Update details w.r.t Extended VD + * input: + * sc - Controller's softc +*/ +static void +mrsas_update_ext_vd_details(struct mrsas_softc *sc) +{ + sc->max256vdSupport = + sc->ctrl_info->adapterOperations3.supportMaxExtLDs; + /* Below is additional check to address future FW enhancement */ + if (sc->ctrl_info->max_lds > 64) + sc->max256vdSupport = 1; + + sc->drv_supported_vd_count = MRSAS_MAX_LD_CHANNELS + * MRSAS_MAX_DEV_PER_CHANNEL; + sc->drv_supported_pd_count = MRSAS_MAX_PD_CHANNELS + * MRSAS_MAX_DEV_PER_CHANNEL; + if (sc->max256vdSupport) { + sc->fw_supported_vd_count = MAX_LOGICAL_DRIVES_EXT; + sc->fw_supported_pd_count = MAX_PHYSICAL_DEVICES; + } else { + sc->fw_supported_vd_count = MAX_LOGICAL_DRIVES; + sc->fw_supported_pd_count = MAX_PHYSICAL_DEVICES; + } + + sc->old_map_sz = sizeof(MR_FW_RAID_MAP) + + (sizeof(MR_LD_SPAN_MAP) * + (sc->fw_supported_vd_count - 1)); + sc->new_map_sz = sizeof(MR_FW_RAID_MAP_EXT); + sc->drv_map_sz = sizeof(MR_DRV_RAID_MAP) + + (sizeof(MR_LD_SPAN_MAP) * + (sc->drv_supported_vd_count - 1)); + + sc->max_map_sz = max(sc->old_map_sz, sc->new_map_sz); + + if (sc->max256vdSupport) + sc->current_map_sz = sc->new_map_sz; + else + sc->current_map_sz = sc->old_map_sz; +} + +/* * mrsas_alloc_ctlr_info_cmd: Allocates memory for controller info command * input: Adapter soft state * @@ -3762,7 +3872,7 @@ mrsas_get_ld_list(struct mrsas_softc *sc) * memory is initialized to all zeros upon successful loading of the dma * mapped memory. */ -int +int mrsas_alloc_tmp_dcmd(struct mrsas_softc *sc, struct mrsas_tmp_dcmd *tcmd, int size) { @@ -3995,10 +4105,12 @@ mrsas_complete_aen(struct mrsas_softc *sc, struct mrsas_mfi_cmd *cmd) */ if ((!cmd->abort_aen) && (sc->remove_in_progress == 0)) { sc->mrsas_aen_triggered = 1; + mtx_lock(&sc->aen_lock); if (sc->mrsas_poll_waiting) { sc->mrsas_poll_waiting = 0; selwakeup(&sc->mrsas_select); } + mtx_unlock(&sc->aen_lock); } else cmd->abort_aen = 0; diff --git a/sys/dev/mrsas/mrsas.h b/sys/dev/mrsas/mrsas.h index 37b6e95..1cfe89e 100644 --- a/sys/dev/mrsas/mrsas.h +++ b/sys/dev/mrsas/mrsas.h @@ -1,6 +1,7 @@ /* + * Copyright (c) 2015, AVAGO Tech. All rights reserved. Authors: Marian Choy * Copyright (c) 2014, LSI Corp. All rights reserved. Authors: Marian Choy - * Support: freebsdraid@lsi.com + * Support: freebsdraid@avagotech.com * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are @@ -31,7 +32,7 @@ * those of the authors and should not be interpreted as representing * official policies,either expressed or implied, of the FreeBSD Project. * - * Send feedback to: <megaraidfbsd@lsi.com> Mail to: LSI Corporation, 1621 + * Send feedback to: <megaraidfbsd@avagotech.com> Mail to: AVAGO TECHNOLOGIES, 1621 * Barber Lane, Milpitas, CA 95035 ATTN: MegaRaid FreeBSD * */ @@ -101,7 +102,7 @@ __FBSDID("$FreeBSD$"); */ #define BYTE_ALIGNMENT 1 #define MRSAS_MAX_NAME_LENGTH 32 -#define MRSAS_VERSION "06.705.10.02-fbsd" +#define MRSAS_VERSION "06.707.04.03-fbsd" #define MRSAS_ULONG_MAX 0xFFFFFFFFFFFFFFFF #define MRSAS_DEFAULT_TIMEOUT 0x14 /* Temporarily set */ #define DONE 0 @@ -813,9 +814,8 @@ typedef struct _MR_DRV_RAID_MAP_ALL { typedef struct _LD_LOAD_BALANCE_INFO { u_int8_t loadBalanceFlag; u_int8_t reserved1; - u_int16_t raid1DevHandle[2]; - mrsas_atomic_t scsi_pending_cmds[2]; - u_int64_t last_accessed_block[2]; + mrsas_atomic_t scsi_pending_cmds[MAX_PHYSICAL_DEVICES]; + u_int64_t last_accessed_block[MAX_PHYSICAL_DEVICES]; } LD_LOAD_BALANCE_INFO, *PLD_LOAD_BALANCE_INFO; /* SPAN_SET is info caclulated from span info from Raid map per ld */ @@ -858,6 +858,9 @@ struct IO_REQUEST_INFO { u_int8_t start_span; u_int8_t reserved; u_int64_t start_row; + /* span[7:5], arm[4:0] */ + u_int8_t span_arm; + u_int8_t pd_after_lb; }; typedef struct _MR_LD_TARGET_SYNC { @@ -1315,6 +1318,13 @@ typedef enum _REGION_TYPE { #define MRSAS_REQ_STATE_TRAN 2 #define MRSAS_REQ_STATE_COMPLETE 3 +typedef enum _MR_SCSI_CMD_TYPE { + READ_WRITE_LDIO = 0, + NON_READ_WRITE_LDIO = 1, + READ_WRITE_SYSPDIO = 2, + NON_READ_WRITE_SYSPDIO = 3, +} MR_SCSI_CMD_TYPE; + enum mrsas_req_flags { MRSAS_DIR_UNKNOWN = 0x1, MRSAS_DIR_IN = 0x2, @@ -1350,6 +1360,7 @@ struct mrsas_mpt_cmd { u_int32_t sync_cmd_idx; u_int32_t index; u_int8_t flags; + u_int8_t pd_r1_lb; u_int8_t load_balance; bus_size_t length; u_int32_t error_code; @@ -1897,9 +1908,26 @@ struct mrsas_ctrl_info { char reserved6[4]; /* 0x7E4 RESERVED FOR IOV */ struct { /* 0x7E8 */ - u_int32_t resrved:5; + u_int32_t supportPersonalityChange:2; + u_int32_t supportThermalPollInterval:1; + u_int32_t supportDisableImmediateIO:1; + u_int32_t supportT10RebuildAssist:1; u_int32_t supportMaxExtLDs:1; - u_int32_t reserved1:26; + u_int32_t supportCrashDump:1; + u_int32_t supportSwZone:1; + u_int32_t supportDebugQueue:1; + u_int32_t supportNVCacheErase:1; + u_int32_t supportForceTo512e:1; + u_int32_t supportHOQRebuild:1; + u_int32_t supportAllowedOpsforDrvRemoval:1; + u_int32_t supportDrvActivityLEDSetting:1; + u_int32_t supportNVDRAM:1; + u_int32_t supportForceFlash:1; + u_int32_t supportDisableSESMonitoring:1; + u_int32_t supportCacheBypassModes:1; + u_int32_t supportSecurityonJBOD:1; + u_int32_t discardCacheDuringLDDelete:1; + u_int32_t reserved:12; } adapterOperations3; u_int8_t pad[0x800 - 0x7EC]; /* 0x7EC */ @@ -1970,7 +1998,10 @@ typedef union _MFI_CAPABILITIES { 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; + 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; } mfi_capabilities; u_int32_t reg; } MFI_CAPABILITIES; @@ -2413,6 +2444,167 @@ struct mrsas_mgmt_info { int max_index; }; +#define PCI_TYPE0_ADDRESSES 6 +#define PCI_TYPE1_ADDRESSES 2 +#define PCI_TYPE2_ADDRESSES 5 + +typedef struct _MRSAS_DRV_PCI_COMMON_HEADER { + u_int16_t vendorID; + //(ro) + u_int16_t deviceID; + //(ro) + u_int16_t command; + //Device control + u_int16_t status; + u_int8_t revisionID; + //(ro) + u_int8_t progIf; + //(ro) + u_int8_t subClass; + //(ro) + u_int8_t baseClass; + //(ro) + u_int8_t cacheLineSize; + //(ro +) + u_int8_t latencyTimer; + //(ro +) + u_int8_t headerType; + //(ro) + u_int8_t bist; + //Built in self test + + union { + struct _MRSAS_DRV_PCI_HEADER_TYPE_0 { + u_int32_t baseAddresses[PCI_TYPE0_ADDRESSES]; + u_int32_t cis; + u_int16_t subVendorID; + u_int16_t subSystemID; + u_int32_t romBaseAddress; + u_int8_t capabilitiesPtr; + u_int8_t reserved1[3]; + u_int32_t reserved2; + u_int8_t interruptLine; + u_int8_t interruptPin; + //(ro) + u_int8_t minimumGrant; + //(ro) + u_int8_t maximumLatency; + //(ro) + } type0; + + /* + * PCI to PCI Bridge + */ + + struct _MRSAS_DRV_PCI_HEADER_TYPE_1 { + u_int32_t baseAddresses[PCI_TYPE1_ADDRESSES]; + u_int8_t primaryBus; + u_int8_t secondaryBus; + u_int8_t subordinateBus; + u_int8_t secondaryLatency; + u_int8_t ioBase; + u_int8_t ioLimit; + u_int16_t secondaryStatus; + u_int16_t memoryBase; + u_int16_t memoryLimit; + u_int16_t prefetchBase; + u_int16_t prefetchLimit; + u_int32_t prefetchBaseUpper32; + u_int32_t prefetchLimitUpper32; + u_int16_t ioBaseUpper16; + u_int16_t ioLimitUpper16; + u_int8_t capabilitiesPtr; + u_int8_t reserved1[3]; + u_int32_t romBaseAddress; + u_int8_t interruptLine; + u_int8_t interruptPin; + u_int16_t bridgeControl; + } type1; + + /* + * PCI to CARDBUS Bridge + */ + + struct _MRSAS_DRV_PCI_HEADER_TYPE_2 { + u_int32_t socketRegistersBaseAddress; + u_int8_t capabilitiesPtr; + u_int8_t reserved; + u_int16_t secondaryStatus; + u_int8_t primaryBus; + u_int8_t secondaryBus; + u_int8_t subordinateBus; + u_int8_t secondaryLatency; + struct { + u_int32_t base; + u_int32_t limit; + } range [PCI_TYPE2_ADDRESSES - 1]; + u_int8_t interruptLine; + u_int8_t interruptPin; + u_int16_t bridgeControl; + } type2; + } u; + +} MRSAS_DRV_PCI_COMMON_HEADER, *PMRSAS_DRV_PCI_COMMON_HEADER; + +#define MRSAS_DRV_PCI_COMMON_HEADER_SIZE sizeof(MRSAS_DRV_PCI_COMMON_HEADER) //64 bytes + +typedef struct _MRSAS_DRV_PCI_LINK_CAPABILITY { + union { + struct { + u_int32_t linkSpeed:4; + u_int32_t linkWidth:6; + u_int32_t aspmSupport:2; + u_int32_t losExitLatency:3; + u_int32_t l1ExitLatency:3; + u_int32_t rsvdp:6; + u_int32_t portNumber:8; + } bits; + + u_int32_t asUlong; + } u; +} MRSAS_DRV_PCI_LINK_CAPABILITY, *PMRSAS_DRV_PCI_LINK_CAPABILITY; + +#define MRSAS_DRV_PCI_LINK_CAPABILITY_SIZE sizeof(MRSAS_DRV_PCI_LINK_CAPABILITY) + +typedef struct _MRSAS_DRV_PCI_LINK_STATUS_CAPABILITY { + union { + struct { + u_int16_t linkSpeed:4; + u_int16_t negotiatedLinkWidth:6; + u_int16_t linkTrainingError:1; + u_int16_t linkTraning:1; + u_int16_t slotClockConfig:1; + u_int16_t rsvdZ:3; + } bits; + + u_int16_t asUshort; + } u; + u_int16_t reserved; +} MRSAS_DRV_PCI_LINK_STATUS_CAPABILITY, *PMRSAS_DRV_PCI_LINK_STATUS_CAPABILITY; + +#define MRSAS_DRV_PCI_LINK_STATUS_CAPABILITY_SIZE sizeof(MRSAS_DRV_PCI_LINK_STATUS_CAPABILITY) + + +typedef struct _MRSAS_DRV_PCI_CAPABILITIES { + MRSAS_DRV_PCI_LINK_CAPABILITY linkCapability; + MRSAS_DRV_PCI_LINK_STATUS_CAPABILITY linkStatusCapability; +} MRSAS_DRV_PCI_CAPABILITIES, *PMRSAS_DRV_PCI_CAPABILITIES; + +#define MRSAS_DRV_PCI_CAPABILITIES_SIZE sizeof(MRSAS_DRV_PCI_CAPABILITIES) + +/* PCI information */ +typedef struct _MRSAS_DRV_PCI_INFORMATION { + u_int32_t busNumber; + u_int8_t deviceNumber; + u_int8_t functionNumber; + u_int8_t interruptVector; + u_int8_t reserved1; + MRSAS_DRV_PCI_COMMON_HEADER pciHeaderInfo; + MRSAS_DRV_PCI_CAPABILITIES capability; + u_int32_t domainID; + u_int8_t reserved2[28]; +} MRSAS_DRV_PCI_INFORMATION, *PMRSAS_DRV_PCI_INFORMATION; + /******************************************************************* * per-instance data ********************************************************************/ @@ -2476,6 +2668,7 @@ struct mrsas_softc { int msix_vectors; int msix_enable; uint32_t msix_reg_offset[16]; + uint8_t mask_interrupts; struct mrsas_mpt_cmd **mpt_cmd_list; struct mrsas_mfi_cmd **mfi_cmd_list; TAILQ_HEAD(, mrsas_mpt_cmd) mrsas_mpt_cmd_list_head; @@ -2519,6 +2712,7 @@ struct mrsas_softc { bus_dmamap_t evt_detail_dmamap; struct mrsas_evt_detail *evt_detail_mem; bus_addr_t evt_detail_phys_addr; + struct mrsas_ctrl_info *ctrl_info; bus_dma_tag_t ctlr_info_tag; bus_dmamap_t ctlr_info_dmamap; void *ctlr_info_mem; @@ -2546,9 +2740,11 @@ struct mrsas_softc { struct task ev_task; u_int32_t CurLdCount; u_int64_t reset_flags; + int lb_pending_cmds; LD_LOAD_BALANCE_INFO load_balance_info[MAX_LOGICAL_DRIVES_EXT]; LD_SPAN_INFO log_to_span[MAX_LOGICAL_DRIVES_EXT]; + u_int8_t secure_jbod_support; 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 80ddc39..08f9002 100644 --- a/sys/dev/mrsas/mrsas_cam.c +++ b/sys/dev/mrsas/mrsas_cam.c @@ -1,6 +1,7 @@ /* + * Copyright (c) 2015, AVAGO Tech. All rights reserved. Author: Marian Choy * Copyright (c) 2014, LSI Corp. All rights reserved. Author: Marian Choy - * Support: freebsdraid@lsi.com + * Support: freebsdraid@avagotech.com * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are @@ -57,17 +58,19 @@ __FBSDID("$FreeBSD$"); * Function prototypes */ int mrsas_cam_attach(struct mrsas_softc *sc); -int mrsas_ldio_inq(struct cam_sim *sim, union ccb *ccb); +int mrsas_find_io_type(struct cam_sim *sim, union ccb *ccb); int mrsas_bus_scan(struct mrsas_softc *sc); int mrsas_bus_scan_sim(struct mrsas_softc *sc, struct cam_sim *sim); -int mrsas_map_request(struct mrsas_softc *sc, struct mrsas_mpt_cmd *cmd); 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, union ccb *ccb); -int +int mrsas_build_dcdb(struct mrsas_softc *sc, struct mrsas_mpt_cmd *cmd, union ccb *ccb, struct cam_sim *sim); -int +int mrsas_setup_io(struct mrsas_softc *sc, struct mrsas_mpt_cmd *cmd, union ccb *ccb, u_int32_t device_id, MRSAS_RAID_SCSI_IO_REQUEST * io_request); @@ -77,10 +80,10 @@ void mrsas_cam_detach(struct mrsas_softc *sc); void mrsas_release_mpt_cmd(struct mrsas_mpt_cmd *cmd); void mrsas_unmap_request(struct mrsas_softc *sc, struct mrsas_mpt_cmd *cmd); void mrsas_cmd_done(struct mrsas_softc *sc, struct mrsas_mpt_cmd *cmd); -void +void mrsas_fire_cmd(struct mrsas_softc *sc, u_int32_t req_desc_lo, u_int32_t req_desc_hi); -void +void mrsas_set_pd_lba(MRSAS_RAID_SCSI_IO_REQUEST * io_request, u_int8_t cdb_len, struct IO_REQUEST_INFO *io_info, union ccb *ccb, MR_DRV_RAID_MAP_ALL * local_map_ptr, u_int32_t ref_tag, @@ -89,10 +92,10 @@ static void mrsas_freeze_simq(struct mrsas_mpt_cmd *cmd, struct cam_sim *sim); static void mrsas_cam_poll(struct cam_sim *sim); static void mrsas_action(struct cam_sim *sim, union ccb *ccb); static void mrsas_scsiio_timeout(void *data); -static void +static void mrsas_data_load_cb(void *arg, bus_dma_segment_t *segs, int nseg, int error); -static int32_t +static int32_t mrsas_startio(struct mrsas_softc *sc, struct cam_sim *sim, union ccb *ccb); struct mrsas_mpt_cmd *mrsas_get_mpt_cmd(struct mrsas_softc *sc); @@ -112,9 +115,9 @@ MR_BuildRaidContext(struct mrsas_softc *sc, extern u_int16_t MR_LdSpanArrayGet(u_int32_t ld, u_int32_t span, MR_DRV_RAID_MAP_ALL * map); -extern u_int16_t -mrsas_get_updated_dev_handle(PLD_LOAD_BALANCE_INFO lbInfo, - struct IO_REQUEST_INFO *io_info); +extern u_int16_t +mrsas_get_updated_dev_handle(struct mrsas_softc *sc, + PLD_LOAD_BALANCE_INFO lbInfo, struct IO_REQUEST_INFO *io_info); 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); @@ -315,7 +318,11 @@ mrsas_action(struct cam_sim *sim, union ccb *ccb) ccb->cpi.version_num = 1; ccb->cpi.hba_inquiry = 0; ccb->cpi.target_sprt = 0; +#if (__FreeBSD_version >= 902001) + ccb->cpi.hba_misc = PIM_UNMAPPED; +#else ccb->cpi.hba_misc = 0; +#endif ccb->cpi.hba_eng_cnt = 0; ccb->cpi.max_lun = MRSAS_SCSI_MAX_LUNS; ccb->cpi.unit_number = cam_sim_unit(sim); @@ -323,7 +330,7 @@ mrsas_action(struct cam_sim *sim, union ccb *ccb) ccb->cpi.initiator_id = MRSAS_SCSI_INITIATOR_ID; ccb->cpi.base_transfer_speed = 150000; strncpy(ccb->cpi.sim_vid, "FreeBSD", SIM_IDLEN); - strncpy(ccb->cpi.hba_vid, "LSI", HBA_IDLEN); + strncpy(ccb->cpi.hba_vid, "AVAGO", HBA_IDLEN); strncpy(ccb->cpi.dev_name, cam_sim_name(sim), DEV_IDLEN); ccb->cpi.transport = XPORT_SPI; ccb->cpi.transport_version = 2; @@ -378,8 +385,13 @@ mrsas_scsiio_timeout(void *data) * on OCR enable/disable property of Controller from ocr_thread * context. */ +#if (__FreeBSD_version >= 1000510) callout_reset_sbt(&cmd->cm_callout, SBT_1S * 600, 0, - mrsas_scsiio_timeout, cmd, 0); + mrsas_scsiio_timeout, cmd, 0); +#else + callout_reset(&cmd->cm_callout, (600000 * hz) / 1000, + mrsas_scsiio_timeout, cmd); +#endif sc->do_timedout_reset = 1; if (sc->ocr_thread_active) wakeup(&sc->ocr_chan); @@ -425,8 +437,8 @@ mrsas_startio(struct mrsas_softc *sc, struct cam_sim *sim, } else cmd->flags = MRSAS_DIR_NONE; /* no data */ - /* For FreeBSD 10.0 and higher */ -#if (__FreeBSD_version >= 1000000) +/* For FreeBSD 9.2 and higher */ +#if (__FreeBSD_version >= 902001) /* * XXX We don't yet support physical addresses here. */ @@ -455,6 +467,11 @@ mrsas_startio(struct mrsas_softc *sc, struct cam_sim *sim, if (cmd->length) cmd->data = csio->data_ptr; break; + case CAM_DATA_BIO: + cmd->length = csio->dxfer_len; + if (cmd->length) + cmd->data = csio->data_ptr; + break; default: ccb->ccb_h.status = CAM_REQ_INVALID; goto done; @@ -499,7 +516,9 @@ mrsas_startio(struct mrsas_softc *sc, struct cam_sim *sim, bcopy(csio->cdb_io.cdb_bytes, cmd->io_request->CDB.CDB32, csio->cdb_len); mtx_lock(&sc->raidmap_lock); - if (mrsas_ldio_inq(sim, ccb)) { + /* Check for IO type READ-WRITE targeted for Logical Volume */ + if (mrsas_find_io_type(sim, ccb) == 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"); mtx_unlock(&sc->raidmap_lock); @@ -530,8 +549,13 @@ mrsas_startio(struct mrsas_softc *sc, struct cam_sim *sim, /* * Start timer for IO timeout. Default timeout value is 90 second. */ - callout_reset_sbt(&cmd->cm_callout, SBT_1MS * sc->mrsas_io_timeout, 0, +#if (__FreeBSD_version >= 1000510) + callout_reset_sbt(&cmd->cm_callout, SBT_1S * 600, 0, mrsas_scsiio_timeout, cmd, 0); +#else + callout_reset(&cmd->cm_callout, (600000 * hz) / 1000, + mrsas_scsiio_timeout, cmd); +#endif mrsas_atomic_inc(&sc->fw_outstanding); if (mrsas_atomic_read(&sc->fw_outstanding) > sc->io_cmds_highwater) @@ -546,20 +570,17 @@ done: } /* - * mrsas_ldio_inq: Determines if IO is read/write or inquiry + * mrsas_find_io_type: Determines if IO is read/write or inquiry * input: pointer to CAM Control Block * * This function determines if the IO is read/write or inquiry. It returns a 1 * if the IO is read/write and 0 if it is inquiry. */ -int -mrsas_ldio_inq(struct cam_sim *sim, union ccb *ccb) +int +mrsas_find_io_type(struct cam_sim *sim, union ccb *ccb) { struct ccb_scsiio *csio = &(ccb->csio); - if (cam_sim_bus(sim) == 1) - return (0); - switch (csio->cdb_io.cdb_bytes[0]) { case READ_10: case WRITE_10: @@ -569,9 +590,11 @@ mrsas_ldio_inq(struct cam_sim *sim, union ccb *ccb) case WRITE_6: case READ_16: case WRITE_16: - return 1; + return (cam_sim_bus(sim) ? + READ_WRITE_SYSPDIO : READ_WRITE_LDIO); default: - return 0; + return (cam_sim_bus(sim) ? + NON_READ_WRITE_SYSPDIO : NON_READ_WRITE_LDIO); } } @@ -677,7 +700,7 @@ mrsas_build_ldio(struct mrsas_softc *sc, struct mrsas_mpt_cmd *cmd, io_request->DataLength = cmd->length; - if (mrsas_map_request(sc, cmd) == SUCCESS) { + if (mrsas_map_request(sc, cmd, ccb) == SUCCESS) { if (cmd->sge_count > MRSAS_MAX_SGL) { device_printf(sc->mrsas_dev, "Error: sge_count (0x%x) exceeds" "max (0x%x) allowed\n", cmd->sge_count, sc->max_num_sge); @@ -824,9 +847,10 @@ mrsas_setup_io(struct mrsas_softc *sc, struct mrsas_mpt_cmd *cmd, if ((sc->load_balance_info[device_id].loadBalanceFlag) && (io_info.isRead)) { io_info.devHandle = - mrsas_get_updated_dev_handle(&sc->load_balance_info[device_id], - &io_info); + mrsas_get_updated_dev_handle(sc, + &sc->load_balance_info[device_id], &io_info); cmd->load_balance = MRSAS_LOAD_BALANCE_FLAG; + cmd->pd_r1_lb = io_info.pd_after_lb; } else cmd->load_balance = 0; cmd->request_desc->SCSIIO.DevHandle = io_info.devHandle; @@ -876,30 +900,49 @@ mrsas_build_dcdb(struct mrsas_softc *sc, struct mrsas_mpt_cmd *cmd, device_id = ccb_h->target_id; map_ptr = sc->ld_drv_map[(sc->map_id & 1)]; - /* Check if this is for system PD */ + /* + * 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) { - io_request->Function = 0; - io_request->DevHandle = map_ptr->raidMap.devHndlInfo[device_id]. - curDevHdl; - io_request->RaidContext.timeoutValue = map_ptr->raidMap.fpPdIoTimeoutSec; - io_request->RaidContext.regLockFlags = 0; - io_request->RaidContext.regLockRowLBA = 0; - io_request->RaidContext.regLockLength = 0; - io_request->RaidContext.RAIDFlags = MR_RAID_FLAGS_IO_SUB_TYPE_SYSTEM_PD - << MR_RAID_CTX_RAID_FLAGS_IO_SUB_TYPE_SHIFT; - if ((sc->device_id == MRSAS_INVADER) || (sc->device_id == MRSAS_FURY)) - 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); - cmd->request_desc->SCSIIO.DevHandle = + 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); + + /* + * 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; + } } else { + /* FW path for SysPD or 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 = @@ -911,7 +954,7 @@ mrsas_build_dcdb(struct mrsas_softc *sc, struct mrsas_mpt_cmd *cmd, io_request->LUN[1] = ccb_h->target_lun & 0xF; io_request->DataLength = cmd->length; - if (mrsas_map_request(sc, cmd) == SUCCESS) { + 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); @@ -934,20 +977,25 @@ mrsas_build_dcdb(struct mrsas_softc *sc, struct mrsas_mpt_cmd *cmd, * is built in the callback. If the bus dmamap load is not successful, * cmd->error_code will contain the error code and a 1 is returned. */ -int -mrsas_map_request(struct mrsas_softc *sc, struct mrsas_mpt_cmd *cmd) +int +mrsas_map_request(struct mrsas_softc *sc, + struct mrsas_mpt_cmd *cmd, union ccb *ccb) { u_int32_t retcode = 0; struct cam_sim *sim; - int flag = BUS_DMA_NOWAIT; sim = xpt_path_sim(cmd->ccb_ptr->ccb_h.path); if (cmd->data != NULL) { - mtx_lock(&sc->io_lock); /* Map data buffer into bus space */ + mtx_lock(&sc->io_lock); +#if (__FreeBSD_version >= 902001) + retcode = bus_dmamap_load_ccb(sc->data_tag, cmd->data_dmamap, ccb, + mrsas_data_load_cb, cmd, 0); +#else retcode = bus_dmamap_load(sc->data_tag, cmd->data_dmamap, cmd->data, - cmd->length, mrsas_data_load_cb, cmd, flag); + cmd->length, mrsas_data_load_cb, cmd, BUS_DMA_NOWAIT); +#endif mtx_unlock(&sc->io_lock); if (retcode) device_printf(sc->mrsas_dev, "bus_dmamap_load(): retcode = %d\n", retcode); diff --git a/sys/dev/mrsas/mrsas_fp.c b/sys/dev/mrsas/mrsas_fp.c index cd0d57f..7ae5662 100644 --- a/sys/dev/mrsas/mrsas_fp.c +++ b/sys/dev/mrsas/mrsas_fp.c @@ -1,6 +1,7 @@ /* + * Copyright (c) 2015, AVAGO Tech. All rights reserved. Author: Marian Choy * Copyright (c) 2014, LSI Corp. All rights reserved. Author: Marian Choy - * Support: freebsdraid@lsi.com + * Support: freebsdraid@avagotech.com * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are @@ -31,7 +32,7 @@ * those of the authors and should not be interpreted as representing * official policies,either expressed or implied, of the FreeBSD Project. * - * Send feedback to: <megaraidfbsd@lsi.com> Mail to: LSI Corporation, 1621 + * Send feedback to: <megaraidfbsd@avagotech.com> Mail to: AVAGO TECHNOLOGIES, 1621 * Barber Lane, Milpitas, CA 95035 ATTN: MegaRaid FreeBSD * */ @@ -55,13 +56,13 @@ __FBSDID("$FreeBSD$"); */ u_int8_t MR_ValidateMapInfo(struct mrsas_softc *sc); u_int8_t -mrsas_get_best_arm(PLD_LOAD_BALANCE_INFO lbInfo, u_int8_t arm, - u_int64_t block, u_int32_t count); -u_int8_t +mrsas_get_best_arm_pd(struct mrsas_softc *sc, + PLD_LOAD_BALANCE_INFO lbInfo, struct IO_REQUEST_INFO *io_info); +u_int8_t MR_BuildRaidContext(struct mrsas_softc *sc, struct IO_REQUEST_INFO *io_info, RAID_CONTEXT * pRAID_Context, MR_DRV_RAID_MAP_ALL * map); -u_int8_t +u_int8_t MR_GetPhyParams(struct mrsas_softc *sc, u_int32_t ld, u_int64_t stripRow, u_int16_t stripRef, struct IO_REQUEST_INFO *io_info, RAID_CONTEXT * pRAID_Context, @@ -70,32 +71,32 @@ u_int16_t MR_TargetIdToLdGet(u_int32_t ldTgtId, MR_DRV_RAID_MAP_ALL * map); u_int32_t MR_LdBlockSizeGet(u_int32_t ldTgtId, MR_DRV_RAID_MAP_ALL * map); u_int16_t MR_GetLDTgtId(u_int32_t ld, MR_DRV_RAID_MAP_ALL * map); u_int16_t -mrsas_get_updated_dev_handle(PLD_LOAD_BALANCE_INFO lbInfo, - struct IO_REQUEST_INFO *io_info); +mrsas_get_updated_dev_handle(struct mrsas_softc *sc, + PLD_LOAD_BALANCE_INFO lbInfo, struct IO_REQUEST_INFO *io_info); u_int32_t mega_mod64(u_int64_t dividend, u_int32_t divisor); -u_int32_t +u_int32_t MR_GetSpanBlock(u_int32_t ld, u_int64_t row, u_int64_t *span_blk, MR_DRV_RAID_MAP_ALL * map, int *div_error); u_int64_t mega_div64_32(u_int64_t dividend, u_int32_t divisor); void -mrsas_update_load_balance_params(MR_DRV_RAID_MAP_ALL * map, - PLD_LOAD_BALANCE_INFO lbInfo); -void +mrsas_update_load_balance_params(struct mrsas_softc *sc, + MR_DRV_RAID_MAP_ALL * map, PLD_LOAD_BALANCE_INFO lbInfo); +void mrsas_set_pd_lba(MRSAS_RAID_SCSI_IO_REQUEST * io_request, u_int8_t cdb_len, struct IO_REQUEST_INFO *io_info, union ccb *ccb, MR_DRV_RAID_MAP_ALL * local_map_ptr, u_int32_t ref_tag, u_int32_t ld_block_size); -static u_int16_t +static u_int16_t MR_LdSpanArrayGet(u_int32_t ld, u_int32_t span, MR_DRV_RAID_MAP_ALL * map); static u_int16_t MR_PdDevHandleGet(u_int32_t pd, MR_DRV_RAID_MAP_ALL * map); -static u_int16_t +static u_int16_t MR_ArPdGet(u_int32_t ar, u_int32_t arm, MR_DRV_RAID_MAP_ALL * map); static MR_LD_SPAN * MR_LdSpanPtrGet(u_int32_t ld, u_int32_t span, MR_DRV_RAID_MAP_ALL * map); -static u_int8_t +static u_int8_t MR_LdDataArmGet(u_int32_t ld, u_int32_t armIdx, MR_DRV_RAID_MAP_ALL * map); static MR_SPAN_BLOCK_INFO * @@ -146,6 +147,8 @@ typedef u_int32_t REGION_LEN; #define FALSE 0 #define TRUE 1 +#define LB_PENDING_CMDS_DEFAULT 4 + /* * Related Macros @@ -376,10 +379,9 @@ MR_ValidateMapInfo(struct mrsas_softc *sc) return 1; } if (sc->UnevenSpanSupport) { - printf("Updating span set\n\n"); mr_update_span_set(drv_map, ldSpanInfo); } - mrsas_update_load_balance_params(drv_map, sc->load_balance_info); + mrsas_update_load_balance_params(sc, drv_map, sc->load_balance_info); return 0; } @@ -566,12 +568,12 @@ get_row_from_strip(struct mrsas_softc *sc, else break; } - mrsas_dprint(sc, MRSAS_PRL11, "LSI Debug : Strip 0x%llx, span_set_Strip 0x%llx, span_set_Row 0x%llx " + mrsas_dprint(sc, MRSAS_PRL11, "AVAGO Debug : Strip 0x%llx, span_set_Strip 0x%llx, span_set_Row 0x%llx " "data width 0x%llx span offset 0x%llx\n", (unsigned long long)strip, (unsigned long long)span_set_Strip, (unsigned long long)span_set_Row, (unsigned long long)span_set->span_row_data_width, (unsigned long long)span_offset); - mrsas_dprint(sc, MRSAS_PRL11, "LSI Debug : For strip 0x%llx row is 0x%llx\n", (unsigned long long)strip, + mrsas_dprint(sc, MRSAS_PRL11, "AVAGO Debug : For strip 0x%llx row is 0x%llx\n", (unsigned long long)strip, (unsigned long long)span_set->data_row_start + (unsigned long long)span_set_Row + (span_offset - 1)); return (span_set->data_row_start + span_set_Row + (span_offset - 1)); @@ -631,7 +633,7 @@ get_strip_from_row(struct mrsas_softc *sc, } } } - mrsas_dprint(sc, MRSAS_PRL11, "LSI Debug - get_strip_from_row: returns invalid " + mrsas_dprint(sc, MRSAS_PRL11, "AVAGO Debug - get_strip_from_row: returns invalid " "strip for ld=%x, row=%lx\n", ld, (long unsigned int)row); return -1; } @@ -679,13 +681,13 @@ get_arm_from_strip(struct mrsas_softc *sc, else break; } - mrsas_dprint(sc, MRSAS_PRL11, "LSI PRL11: get_arm_from_strip: " + mrsas_dprint(sc, MRSAS_PRL11, "AVAGO PRL11: get_arm_from_strip: " "for ld=0x%x strip=0x%lx arm is 0x%x\n", ld, (long unsigned int)strip, (strip_offset - span_offset)); return (strip_offset - span_offset); } - mrsas_dprint(sc, MRSAS_PRL11, "LSI Debug: - get_arm_from_strip: returns invalid arm" + mrsas_dprint(sc, MRSAS_PRL11, "AVAGO Debug: - get_arm_from_strip: returns invalid arm" " for ld=%x strip=%lx\n", ld, (long unsigned int)strip); return -1; @@ -723,9 +725,11 @@ get_arm(struct mrsas_softc *sc, u_int32_t ld, u_int8_t span, u_int64_t stripe, * This routine calculates the arm, span and block for the specified stripe and * reference in stripe using spanset * - * Inputs : Logical drive number - * stripRow: Stripe number - * stripRef: Reference in stripe + * Inputs : + * sc - HBA instance + * ld - Logical drive number + * stripRow: Stripe number + * stripRef: Reference in stripe * * Outputs : span - Span number block - Absolute Block * number in the physical disk @@ -785,6 +789,7 @@ mr_spanset_get_phy_params(struct mrsas_softc *sc, u_int32_t ld, u_int64_t stripR *pdBlock += stripRef + MR_LdSpanPtrGet(ld, span, map)->startBlk; pRAID_Context->spanArm = (span << RAID_CTX_SPANARM_SPAN_SHIFT) | physArm; + io_info->span_arm = pRAID_Context->spanArm; return retval; } @@ -831,7 +836,7 @@ MR_BuildRaidContext(struct mrsas_softc *sc, struct IO_REQUEST_INFO *io_info, else if (sc->UnevenSpanSupport) { io_info->IoforUnevenSpan = 1; } else { - mrsas_dprint(sc, MRSAS_PRL11, "LSI Debug: raid->rowDataSize is 0, but has SPAN[0] rowDataSize = 0x%0x," + mrsas_dprint(sc, MRSAS_PRL11, "AVAGO Debug: raid->rowDataSize is 0, but has SPAN[0] rowDataSize = 0x%0x," " but there is _NO_ UnevenSpanSupport\n", MR_LdSpanPtrGet(ld, 0, map)->spanRowDataSize); return FALSE; @@ -858,13 +863,13 @@ MR_BuildRaidContext(struct mrsas_softc *sc, struct IO_REQUEST_INFO *io_info, startlba_span = (u_int8_t)mr_spanset_get_span_block(sc, ld, start_row, pdBlock, map, &error_code); if (error_code == 1) { - mrsas_dprint(sc, MRSAS_PRL11, "LSI Debug: return from %s %d. Send IO w/o region lock.\n", + mrsas_dprint(sc, MRSAS_PRL11, "AVAGO Debug: return from %s %d. Send IO w/o region lock.\n", __func__, __LINE__); return FALSE; } } if (startlba_span == SPAN_INVALID) { - mrsas_dprint(sc, MRSAS_PRL11, "LSI Debug: return from %s %d for row 0x%llx," + mrsas_dprint(sc, MRSAS_PRL11, "AVAGO Debug: return from %s %d for row 0x%llx," "start strip %llx endSrip %llx\n", __func__, __LINE__, (unsigned long long)start_row, (unsigned long long)start_strip, @@ -873,12 +878,12 @@ MR_BuildRaidContext(struct mrsas_softc *sc, struct IO_REQUEST_INFO *io_info, } io_info->start_span = startlba_span; io_info->start_row = start_row; - mrsas_dprint(sc, MRSAS_PRL11, "LSI Debug: Check Span number from %s %d for row 0x%llx, " + mrsas_dprint(sc, MRSAS_PRL11, "AVAGO Debug: Check Span number from %s %d for row 0x%llx, " " start strip 0x%llx endSrip 0x%llx span 0x%x\n", __func__, __LINE__, (unsigned long long)start_row, (unsigned long long)start_strip, (unsigned long long)endStrip, startlba_span); - mrsas_dprint(sc, MRSAS_PRL11, "LSI Debug : 1. start_row 0x%llx endRow 0x%llx Start span 0x%x\n", + mrsas_dprint(sc, MRSAS_PRL11, "AVAGO Debug : 1. start_row 0x%llx endRow 0x%llx Start span 0x%x\n", (unsigned long long)start_row, (unsigned long long)endRow, startlba_span); } else { start_row = mega_div64_32(start_strip, raid->rowDataSize); @@ -1042,7 +1047,7 @@ mr_update_span_set(MR_DRV_RAID_MAP_ALL * map, PLD_SPAN_INFO ldSpanInfo) span_row_width += MR_LdSpanPtrGet(ld, count, map)->spanRowDataSize; #if SPAN_DEBUG - printf("LSI Debug span %x rowDataSize %x\n", count, + printf("AVAGO Debug span %x rowDataSize %x\n", count, MR_LdSpanPtrGet(ld, count, map)->spanRowDataSize); #endif } @@ -1097,46 +1102,38 @@ mr_update_span_set(MR_DRV_RAID_MAP_ALL * map, PLD_SPAN_INFO ldSpanInfo) /* * mrsas_update_load_balance_params: Update load balance parmas - * Inputs: map pointer - * Load balance info + * Inputs: + * sc - driver softc instance + * drv_map - driver RAID map + * lbInfo - Load balance info * * This function updates the load balance parameters for the LD config of a two * drive optimal RAID-1. */ -void -mrsas_update_load_balance_params(MR_DRV_RAID_MAP_ALL * map, - PLD_LOAD_BALANCE_INFO lbInfo) +void +mrsas_update_load_balance_params(struct mrsas_softc *sc, + MR_DRV_RAID_MAP_ALL * drv_map, PLD_LOAD_BALANCE_INFO lbInfo) { int ldCount; u_int16_t ld; - u_int32_t pd, arRef; MR_LD_RAID *raid; - for (ldCount = 0; ldCount < MAX_LOGICAL_DRIVES; ldCount++) { - ld = MR_TargetIdToLdGet(ldCount, map); - if (ld >= MAX_LOGICAL_DRIVES) { + if (sc->lb_pending_cmds > 128 || sc->lb_pending_cmds < 1) + sc->lb_pending_cmds = LB_PENDING_CMDS_DEFAULT; + + for (ldCount = 0; ldCount < MAX_LOGICAL_DRIVES_EXT; ldCount++) { + ld = MR_TargetIdToLdGet(ldCount, drv_map); + if (ld >= MAX_LOGICAL_DRIVES_EXT) { lbInfo[ldCount].loadBalanceFlag = 0; continue; } - raid = MR_LdRaidGet(ld, map); - - /* Two drive Optimal RAID 1 */ - if ((raid->level == 1) && (raid->rowSize == 2) && - (raid->spanDepth == 1) - && raid->ldState == MR_LD_STATE_OPTIMAL) { - lbInfo[ldCount].loadBalanceFlag = 1; - - /* Get the array on which this span is present */ - arRef = MR_LdSpanArrayGet(ld, 0, map); - - /* Get the PD */ - pd = MR_ArPdGet(arRef, 0, map); - /* Get dev handle from PD */ - lbInfo[ldCount].raid1DevHandle[0] = MR_PdDevHandleGet(pd, map); - pd = MR_ArPdGet(arRef, 1, map); - lbInfo[ldCount].raid1DevHandle[1] = MR_PdDevHandleGet(pd, map); - } else + raid = MR_LdRaidGet(ld, drv_map); + if ((raid->level != 1) || + (raid->ldState != MR_LD_STATE_OPTIMAL)) { lbInfo[ldCount].loadBalanceFlag = 0; + continue; + } + lbInfo[ldCount].loadBalanceFlag = 1; } } @@ -1152,7 +1149,7 @@ mrsas_update_load_balance_params(MR_DRV_RAID_MAP_ALL * map, * * Used to set the PD logical block address in CDB for FP IOs. */ -void +void mrsas_set_pd_lba(MRSAS_RAID_SCSI_IO_REQUEST * io_request, u_int8_t cdb_len, struct IO_REQUEST_INFO *io_info, union ccb *ccb, MR_DRV_RAID_MAP_ALL * local_map_ptr, u_int32_t ref_tag, @@ -1299,6 +1296,7 @@ mrsas_set_pd_lba(MRSAS_RAID_SCSI_IO_REQUEST * io_request, u_int8_t cdb_len, } /* Fall through normal case, just load LBA here */ u_int8_t val = cdb[1] & 0xE0; + switch (cdb_len) { case 6: cdb[3] = (u_int8_t)(start_blk & 0xff); @@ -1332,57 +1330,94 @@ mrsas_set_pd_lba(MRSAS_RAID_SCSI_IO_REQUEST * io_request, u_int8_t cdb_len, } /* - * mrsas_get_best_arm: Determine the best spindle arm - * Inputs: Load balance info + * mrsas_get_best_arm_pd: Determine the best spindle arm + * Inputs: + * sc - HBA instance + * lbInfo - Load balance info + * io_info - IO request info * * This function determines and returns the best arm by looking at the * parameters of the last PD access. */ -u_int8_t -mrsas_get_best_arm(PLD_LOAD_BALANCE_INFO lbInfo, u_int8_t arm, - u_int64_t block, u_int32_t count) +u_int8_t +mrsas_get_best_arm_pd(struct mrsas_softc *sc, + PLD_LOAD_BALANCE_INFO lbInfo, struct IO_REQUEST_INFO *io_info) { - u_int16_t pend0, pend1; + MR_LD_RAID *raid; + MR_DRV_RAID_MAP_ALL *drv_map; + u_int16_t pend0, pend1, ld; u_int64_t diff0, diff1; - u_int8_t bestArm; + u_int8_t bestArm, pd0, pd1, span, arm; + u_int32_t arRef, span_row_size; + + u_int64_t block = io_info->ldStartBlock; + u_int32_t count = io_info->numBlocks; + + span = ((io_info->span_arm & RAID_CTX_SPANARM_SPAN_MASK) + >> RAID_CTX_SPANARM_SPAN_SHIFT); + arm = (io_info->span_arm & RAID_CTX_SPANARM_ARM_MASK); + + drv_map = sc->ld_drv_map[(sc->map_id & 1)]; + ld = MR_TargetIdToLdGet(io_info->ldTgtId, drv_map); + raid = MR_LdRaidGet(ld, drv_map); + span_row_size = sc->UnevenSpanSupport ? + SPAN_ROW_SIZE(drv_map, ld, span) : raid->rowSize; + + arRef = MR_LdSpanArrayGet(ld, span, drv_map); + pd0 = MR_ArPdGet(arRef, arm, drv_map); + pd1 = MR_ArPdGet(arRef, (arm + 1) >= span_row_size ? + (arm + 1 - span_row_size) : arm + 1, drv_map); /* get the pending cmds for the data and mirror arms */ - pend0 = mrsas_atomic_read(&lbInfo->scsi_pending_cmds[0]); - pend1 = mrsas_atomic_read(&lbInfo->scsi_pending_cmds[1]); + pend0 = mrsas_atomic_read(&lbInfo->scsi_pending_cmds[pd0]); + pend1 = mrsas_atomic_read(&lbInfo->scsi_pending_cmds[pd1]); /* Determine the disk whose head is nearer to the req. block */ - diff0 = ABS_DIFF(block, lbInfo->last_accessed_block[0]); - diff1 = ABS_DIFF(block, lbInfo->last_accessed_block[1]); - bestArm = (diff0 <= diff1 ? 0 : 1); + diff0 = ABS_DIFF(block, lbInfo->last_accessed_block[pd0]); + diff1 = ABS_DIFF(block, lbInfo->last_accessed_block[pd1]); + bestArm = (diff0 <= diff1 ? arm : arm ^ 1); - if ((bestArm == arm && pend0 > pend1 + 16) || (bestArm != arm && pend1 > pend0 + 16)) + if ((bestArm == arm && pend0 > pend1 + sc->lb_pending_cmds) || + (bestArm != arm && pend1 > pend0 + sc->lb_pending_cmds)) bestArm ^= 1; /* Update the last accessed block on the correct pd */ - lbInfo->last_accessed_block[bestArm] = block + count - 1; + lbInfo->last_accessed_block[bestArm == arm ? pd0 : pd1] = block + count - 1; + io_info->span_arm = (span << RAID_CTX_SPANARM_SPAN_SHIFT) | bestArm; + io_info->pd_after_lb = (bestArm == arm) ? pd0 : pd1; +#if SPAN_DEBUG + if (arm != bestArm) + printf("AVAGO Debug R1 Load balance occur - span 0x%x arm 0x%x bestArm 0x%x " + "io_info->span_arm 0x%x\n", + span, arm, bestArm, io_info->span_arm); +#endif - return bestArm; + return io_info->pd_after_lb; } /* * mrsas_get_updated_dev_handle: Get the update dev handle - * Inputs: Load balance info io_info pointer + * Inputs: + * sc - Adapter instance soft state + * lbInfo - Load balance info + * io_info - io_info pointer * * This function determines and returns the updated dev handle. */ -u_int16_t -mrsas_get_updated_dev_handle(PLD_LOAD_BALANCE_INFO lbInfo, - struct IO_REQUEST_INFO *io_info) +u_int16_t +mrsas_get_updated_dev_handle(struct mrsas_softc *sc, + PLD_LOAD_BALANCE_INFO lbInfo, struct IO_REQUEST_INFO *io_info) { - u_int8_t arm, old_arm; + u_int8_t arm_pd; u_int16_t devHandle; + MR_DRV_RAID_MAP_ALL *drv_map; - old_arm = lbInfo->raid1DevHandle[0] == io_info->devHandle ? 0 : 1; + drv_map = sc->ld_drv_map[(sc->map_id & 1)]; /* get best new arm */ - arm = mrsas_get_best_arm(lbInfo, old_arm, io_info->ldStartBlock, io_info->numBlocks); - devHandle = lbInfo->raid1DevHandle[arm]; - mrsas_atomic_inc(&lbInfo->scsi_pending_cmds[arm]); + arm_pd = mrsas_get_best_arm_pd(sc, lbInfo, io_info); + devHandle = MR_PdDevHandleGet(arm_pd, drv_map); + mrsas_atomic_inc(&lbInfo->scsi_pending_cmds[arm_pd]); return devHandle; } @@ -1471,6 +1506,7 @@ MR_GetPhyParams(struct mrsas_softc *sc, u_int32_t ld, *pdBlock += stripRef + MR_LdSpanPtrGet(ld, span, map)->startBlk; pRAID_Context->spanArm = (span << RAID_CTX_SPANARM_SPAN_SHIFT) | physArm; + io_info->span_arm = pRAID_Context->spanArm; return retval; } diff --git a/sys/dev/mrsas/mrsas_ioctl.c b/sys/dev/mrsas/mrsas_ioctl.c index 8e2aead..3c4dbf9 100644 --- a/sys/dev/mrsas/mrsas_ioctl.c +++ b/sys/dev/mrsas/mrsas_ioctl.c @@ -1,6 +1,7 @@ /* + * Copyright (c) 2015, AVAGO Tech. All rights reserved. Author: Marian Choy * Copyright (c) 2014, LSI Corp. All rights reserved. Author: Marian Choy - * Support: freebsdraid@lsi.com + * Support: freebsdraid@avagotech.com * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are @@ -31,7 +32,7 @@ * those of the authors and should not be interpreted as representing * official policies,either expressed or implied, of the FreeBSD Project. * - * Send feedback to: <megaraidfbsd@lsi.com> Mail to: LSI Corporation, 1621 + * Send feedback to: <megaraidfbsd@avagotech.com> Mail to: AVAGO TECHNOLOGIES, 1621 * Barber Lane, Milpitas, CA 95035 ATTN: MegaRaid FreeBSD * */ @@ -238,7 +239,7 @@ mrsas_passthru(struct mrsas_softc *sc, void *arg, u_long ioctlCmd) } sense_ptr = (unsigned long *)((unsigned long)cmd->frame + user_ioc->sense_off); - sense_ptr = ioctl_sense_mem; + *sense_ptr = ioctl_sense_phys_addr; } /* * Set the sync_cmd flag so that the ISR knows not to complete this @@ -296,13 +297,14 @@ out: /* * Release sense buffer */ - if (ioctl_sense_phys_addr) - bus_dmamap_unload(ioctl_sense_tag, ioctl_sense_dmamap); - if (ioctl_sense_mem != NULL) - bus_dmamem_free(ioctl_sense_tag, ioctl_sense_mem, ioctl_sense_dmamap); - if (ioctl_sense_tag != NULL) - bus_dma_tag_destroy(ioctl_sense_tag); - + if (user_ioc->sense_len) { + if (ioctl_sense_phys_addr) + bus_dmamap_unload(ioctl_sense_tag, ioctl_sense_dmamap); + if (ioctl_sense_mem != NULL) + bus_dmamem_free(ioctl_sense_tag, ioctl_sense_mem, ioctl_sense_dmamap); + if (ioctl_sense_tag != NULL) + bus_dma_tag_destroy(ioctl_sense_tag); + } /* * Release data buffers */ diff --git a/sys/dev/mrsas/mrsas_ioctl.h b/sys/dev/mrsas/mrsas_ioctl.h index bf05a7d..c43fc6d 100644 --- a/sys/dev/mrsas/mrsas_ioctl.h +++ b/sys/dev/mrsas/mrsas_ioctl.h @@ -1,6 +1,7 @@ /* + * Copyright (c) 2015, AVAGO Tech. All rights reserved. Author: Marian Choy * Copyright (c) 2014, LSI Corp. All rights reserved. Author: Marian Choy - * Support: freebsdraid@lsi.com + * Support: freebsdraid@avagotech.com * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are @@ -31,7 +32,7 @@ * those of the authors and should not be interpreted as representing * official policies,either expressed or implied, of the FreeBSD Project. * - * Send feedback to: <megaraidfbsd@lsi.com> Mail to: LSI Corporation, 1621 + * Send feedback to: <megaraidfbsd@avagotech.com> Mail to: AVAGO TECHNOLOGIES, 1621 * Barber Lane, Milpitas, CA 95035 ATTN: MegaRaid FreeBSD * */ @@ -64,6 +65,7 @@ __FBSDID("$FreeBSD$"); * into a somewhat unique, 32-bit value. */ +#define MRSAS_IOC_GET_PCI_INFO _IOR('M', 7, MRSAS_DRV_PCI_INFORMATION) #define MRSAS_IOC_FIRMWARE_PASS_THROUGH64 _IOWR('M', 1, struct mrsas_iocpacket) #ifdef COMPAT_FREEBSD32 #define MRSAS_IOC_FIRMWARE_PASS_THROUGH32 _IOWR('M', 1, struct mrsas_iocpacket32) diff --git a/sys/dev/mrsas/mrsas_linux.c b/sys/dev/mrsas/mrsas_linux.c index 8a3db0b..15f38c5 100644 --- a/sys/dev/mrsas/mrsas_linux.c +++ b/sys/dev/mrsas/mrsas_linux.c @@ -1,6 +1,7 @@ /* + * Copyright (c) 2015, AVAGO Tech. All rights reserved. Author: Kashyap Desai, * Copyright (c) 2014, LSI Corp. All rights reserved. Author: Kashyap Desai, - * Sibananda Sahu Support: freebsdraid@lsi.com + * Sibananda Sahu Support: freebsdraid@avagotech.com * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are @@ -31,7 +32,7 @@ * those of the authors and should not be interpreted as representing * official policies,either expressed or implied, of the FreeBSD Project. * - * Send feedback to: <megaraidfbsd@lsi.com> Mail to: LSI Corporation, 1621 + * Send feedback to: <megaraidfbsd@avagotech.com> Mail to: AVAGO TECHNOLOGIES, 1621 * Barber Lane, Milpitas, CA 95035 ATTN: MegaRaid FreeBSD * */ |