summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys/dev/mrsas/mrsas.c690
-rw-r--r--sys/dev/mrsas/mrsas.h63
-rw-r--r--sys/dev/mrsas/mrsas_cam.c282
-rw-r--r--sys/dev/mrsas/mrsas_fp.c21
-rw-r--r--sys/dev/mrsas/mrsas_ioctl.c25
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;
OpenPOWER on IntegriCloud