svn commit: r300736 - stable/10/sys/dev/mrsas
Kashyap D Desai
kadesai at FreeBSD.org
Thu May 26 12:00:16 UTC 2016
Author: kadesai
Date: Thu May 26 12:00:14 2016
New Revision: 300736
URL: https://svnweb.freebsd.org/changeset/base/300736
Log:
MFC r299666 - r299672
r299666: Takes care of any firmware command timeout scenarios by initiating OCR.
r299667: Similar to RAID map for Logical Drives, now JBOD map has been introduced
r299668: This patch implements driver support for 1MB IO size.
r299669: Implemented interrupt Config Hook in mrsas(4) to defer some of the tasks, like:
registering AEN, creating cdev.
r299670: Added support for Avago Intruder controller.
r299671: bugs fixed as part of this patch in kdump and some NULL pointer dereference
r299672: Version update patch.
Sponsored by: AVAGO Technologies/ Broadcom Limited
Modified:
stable/10/sys/dev/mrsas/mrsas.c
stable/10/sys/dev/mrsas/mrsas.h
stable/10/sys/dev/mrsas/mrsas_cam.c
stable/10/sys/dev/mrsas/mrsas_fp.c
stable/10/sys/dev/mrsas/mrsas_ioctl.c
Directory Properties:
stable/10/ (props changed)
Modified: stable/10/sys/dev/mrsas/mrsas.c
==============================================================================
--- stable/10/sys/dev/mrsas/mrsas.c Thu May 26 11:58:36 2016 (r300735)
+++ stable/10/sys/dev/mrsas/mrsas.c Thu May 26 12:00:14 2016 (r300736)
@@ -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_
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 *s
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 *
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
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 *s
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 *s
/* 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 *s
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
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_soft
* 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
* 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_
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 *
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 *s
{
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 *s
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
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
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_sof
{
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_sof
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 mr
(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 mr
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, str
{
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 *
}
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;
+
*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
More information about the svn-src-stable-10
mailing list