summaryrefslogtreecommitdiffstats
path: root/sys/dev/mrsas/mrsas_cam.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev/mrsas/mrsas_cam.c')
-rw-r--r--sys/dev/mrsas/mrsas_cam.c150
1 files changed, 99 insertions, 51 deletions
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);
OpenPOWER on IntegriCloud