svn commit: r235135 - stable/9/sys/dev/mfi
Doug Ambrisko
ambrisko at FreeBSD.org
Mon May 7 19:17:10 UTC 2012
Author: ambrisko
Date: Mon May 7 19:17:09 2012
New Revision: 235135
URL: http://svn.freebsd.org/changeset/base/235135
Log:
MFC r235014: Rebuild fix and LBA calculation fix for ThunderBolt
based cards.
MFC r235016: Some style improvements.
MFC r235040: Fix the returns in mfi_tbolt_sync_map_info that I added.
PR: 167226
Modified:
stable/9/sys/dev/mfi/mfi.c
stable/9/sys/dev/mfi/mfi_debug.c
stable/9/sys/dev/mfi/mfi_disk.c
stable/9/sys/dev/mfi/mfi_tbolt.c
stable/9/sys/dev/mfi/mfireg.h
stable/9/sys/dev/mfi/mfivar.h
Directory Properties:
stable/9/sys/ (props changed)
Modified: stable/9/sys/dev/mfi/mfi.c
==============================================================================
--- stable/9/sys/dev/mfi/mfi.c Mon May 7 18:30:22 2012 (r235134)
+++ stable/9/sys/dev/mfi/mfi.c Mon May 7 19:17:09 2012 (r235135)
@@ -90,8 +90,6 @@ static int mfi_get_controller_info(struc
static int mfi_get_log_state(struct mfi_softc *,
struct mfi_evt_log_state **);
static int mfi_parse_entries(struct mfi_softc *, int, int);
-static int mfi_dcmd_command(struct mfi_softc *, struct mfi_command **,
- uint32_t, void **, size_t);
static void mfi_data_cb(void *, bus_dma_segment_t *, int, int);
static void mfi_startup(void *arg);
static void mfi_intr(void *arg);
@@ -377,6 +375,7 @@ mfi_attach(struct mfi_softc *sc)
TAILQ_INIT(&sc->mfi_syspd_tqh);
TAILQ_INIT(&sc->mfi_evt_queue);
TASK_INIT(&sc->mfi_evt_task, 0, mfi_handle_evt, sc);
+ TASK_INIT(&sc->mfi_map_sync_task, 0, mfi_handle_map_sync, sc);
TAILQ_INIT(&sc->mfi_aen_pids);
TAILQ_INIT(&sc->mfi_cam_ccbq);
@@ -696,7 +695,6 @@ mfi_attach(struct mfi_softc *sc)
return (EINVAL);
}
sc->mfi_enable_intr(sc);
- sc->map_id = 0;
} else {
if ((error = mfi_comms_init(sc)) != 0)
return (error);
@@ -762,6 +760,10 @@ mfi_attach(struct mfi_softc *sc)
callout_reset(&sc->mfi_watchdog_callout, MFI_CMD_TIMEOUT * hz,
mfi_timeout, sc);
+ if (sc->mfi_flags & MFI_FLAGS_TBOLT) {
+ mfi_tbolt_sync_map_info(sc);
+ }
+
return (0);
}
@@ -845,7 +847,7 @@ mfi_release_command(struct mfi_command *
mfi_enqueue_free(cm);
}
-static int
+int
mfi_dcmd_command(struct mfi_softc *sc, struct mfi_command **cmp,
uint32_t opcode, void **bufp, size_t bufsize)
{
@@ -1286,8 +1288,8 @@ mfi_shutdown(struct mfi_softc *sc)
if (sc->mfi_aen_cm != NULL)
mfi_abort(sc, sc->mfi_aen_cm);
- if (sc->map_update_cmd != NULL)
- mfi_abort(sc, sc->map_update_cmd);
+ if (sc->mfi_map_sync_cm != NULL)
+ mfi_abort(sc, sc->mfi_map_sync_cm);
dcmd = &cm->cm_frame->dcmd;
dcmd->header.flags = MFI_FRAME_DIR_NONE;
@@ -1317,7 +1319,7 @@ mfi_syspdprobe(struct mfi_softc *sc)
/* Add SYSTEM PD's */
error = mfi_dcmd_command(sc, &cm, MFI_DCMD_PD_LIST_QUERY,
(void **)&pdlist, sizeof(*pdlist));
- if (error){
+ if (error) {
device_printf(sc->mfi_dev,
"Error while forming SYSTEM PD list\n");
goto out;
@@ -1664,9 +1666,9 @@ mfi_aen_complete(struct mfi_command *cm)
if (sc->mfi_aen_cm == NULL)
return;
- if (sc->mfi_aen_cm->cm_aen_abort ||
+ if (sc->cm_aen_abort ||
hdr->cmd_status == MFI_STAT_INVALID_STATUS) {
- sc->mfi_aen_cm->cm_aen_abort = 0;
+ sc->cm_aen_abort = 0;
aborted = 1;
} else {
sc->mfi_aen_triggered = 1;
@@ -1956,6 +1958,7 @@ mfi_add_sys_pd_complete(struct mfi_comma
mtx_unlock(&Giant);
mtx_lock(&sc->mfi_io_lock);
}
+
static struct mfi_command *
mfi_bio_command(struct mfi_softc *sc)
{
@@ -1963,7 +1966,7 @@ mfi_bio_command(struct mfi_softc *sc)
struct mfi_command *cm = NULL;
/*reserving two commands to avoid starvation for IOCTL*/
- if (sc->mfi_qstat[MFIQ_FREE].q_length < 2){
+ if (sc->mfi_qstat[MFIQ_FREE].q_length < 2) {
return (NULL);
}
if ((bio = mfi_dequeue_bio(sc)) == NULL) {
@@ -2385,7 +2388,9 @@ mfi_abort(struct mfi_softc *sc, struct m
cm->cm_flags = MFI_CMD_POLLED;
if (sc->mfi_aen_cm)
- sc->mfi_aen_cm->cm_aen_abort = 1;
+ sc->cm_aen_abort = 1;
+ if (sc->mfi_map_sync_cm)
+ sc->cm_map_abort = 1;
mfi_mapcmd(sc, cm);
mfi_release_command(cm);
@@ -2394,6 +2399,11 @@ mfi_abort(struct mfi_softc *sc, struct m
5 * hz);
i++;
}
+ while (i < 5 && sc->mfi_map_sync_cm != NULL) {
+ msleep(&sc->mfi_map_sync_cm, &sc->mfi_io_lock, 0, "mfiabort",
+ 5 * hz);
+ i++;
+ }
return (0);
}
@@ -2685,12 +2695,12 @@ static int mfi_check_for_sscd(struct mfi
int error = 0;
if ((cm->cm_frame->dcmd.opcode == MFI_DCMD_CFG_ADD) &&
- (conf_data->ld[0].params.isSSCD == 1)){
+ (conf_data->ld[0].params.isSSCD == 1)) {
error = 1;
} else if (cm->cm_frame->dcmd.opcode == MFI_DCMD_LD_DELETE) {
error = mfi_dcmd_command (sc, &ld_cm, MFI_DCMD_LD_GET_INFO,
(void **)&ld_info, sizeof(*ld_info));
- if (error){
+ if (error) {
device_printf(sc->mfi_dev, "Failed to allocate"
"MFI_DCMD_LD_GET_INFO %d", error);
if (ld_info)
@@ -2700,7 +2710,7 @@ static int mfi_check_for_sscd(struct mfi
ld_cm->cm_flags = MFI_CMD_DATAIN;
ld_cm->cm_frame->dcmd.mbox[0]= cm->cm_frame->dcmd.mbox[0];
ld_cm->cm_frame->header.target_id = cm->cm_frame->dcmd.mbox[0];
- if (mfi_wait_command(sc, ld_cm) != 0){
+ if (mfi_wait_command(sc, ld_cm) != 0) {
device_printf(sc->mfi_dev, "failed to get log drv\n");
mfi_release_command(ld_cm);
free(ld_info, M_MFIBUF);
@@ -3549,9 +3559,9 @@ mfi_timeout(void *data)
}
mtx_lock(&sc->mfi_io_lock);
TAILQ_FOREACH(cm, &sc->mfi_busy, cm_link) {
- if (sc->mfi_aen_cm == cm)
+ if (sc->mfi_aen_cm == cm || sc->mfi_map_sync_cm == cm)
continue;
- if ((sc->mfi_aen_cm != cm) && (cm->cm_timestamp < deadline)) {
+ if (cm->cm_timestamp < deadline) {
if (sc->adpreset != 0 && sc->issuepend_done == 0) {
cm->cm_timestamp = time_uptime;
} else {
Modified: stable/9/sys/dev/mfi/mfi_debug.c
==============================================================================
--- stable/9/sys/dev/mfi/mfi_debug.c Mon May 7 18:30:22 2012 (r235134)
+++ stable/9/sys/dev/mfi/mfi_debug.c Mon May 7 19:17:09 2012 (r235135)
@@ -172,6 +172,9 @@ mfi_print_dcmd(struct mfi_softc *sc, dev
case MFI_DCMD_CLUSTER_RESET_LD:
opcode = "CLUSTER_RESET_LD";
break;
+ case MFI_DCMD_LD_MAP_GET_INFO:
+ opcode = "LD_MAP_GET_INFO";
+ break;
default:
opcode = "UNKNOWN";
break;
Modified: stable/9/sys/dev/mfi/mfi_disk.c
==============================================================================
--- stable/9/sys/dev/mfi/mfi_disk.c Mon May 7 18:30:22 2012 (r235134)
+++ stable/9/sys/dev/mfi/mfi_disk.c Mon May 7 19:17:09 2012 (r235135)
@@ -256,17 +256,17 @@ mfi_disk_strategy(struct bio *bio)
return;
}
- if (controller->adpreset){
+ if (controller->adpreset) {
bio->bio_error = EBUSY;
return;
}
- if (controller->hw_crit_error){
+ if (controller->hw_crit_error) {
bio->bio_error = EBUSY;
return;
}
- if (controller->issuepend_done == 0){
+ if (controller->issuepend_done == 0) {
bio->bio_error = EBUSY;
return;
}
Modified: stable/9/sys/dev/mfi/mfi_tbolt.c
==============================================================================
--- stable/9/sys/dev/mfi/mfi_tbolt.c Mon May 7 18:30:22 2012 (r235134)
+++ stable/9/sys/dev/mfi/mfi_tbolt.c Mon May 7 19:17:09 2012 (r235135)
@@ -82,7 +82,8 @@ map_tbolt_cmd_status(struct mfi_command
static void mfi_issue_pending_cmds_again (struct mfi_softc *sc);
static void mfi_kill_hba (struct mfi_softc *sc);
static void mfi_process_fw_state_chg_isr(void *arg);
-uint8_t mfi_tbolt_get_map_info(struct mfi_softc *sc);
+static void mfi_sync_map_complete(struct mfi_command *);
+static void mfi_queue_map_sync(struct mfi_softc *sc);
#define MFI_FUSION_ENABLE_INTERRUPT_MASK (0x00000008)
@@ -140,11 +141,12 @@ mfi_tbolt_issue_cmd_ppc(struct mfi_softc
MFI_WRITE4(sc, MFI_IQPH, (uint32_t)((uint64_t)bus_add >> 32));
}
-/**
+/*
* mfi_tbolt_adp_reset - For controller reset
* @regs: MFI register set
*/
-int mfi_tbolt_adp_reset(struct mfi_softc *sc)
+int
+mfi_tbolt_adp_reset(struct mfi_softc *sc)
{
int retry = 0, i = 0;
int HostDiag;
@@ -192,12 +194,10 @@ int mfi_tbolt_adp_reset(struct mfi_softc
}
/*
- *******************************************************************************************
- * Description:
- * This routine initialize Thunderbolt specific device information
- *******************************************************************************************
+ * This routine initialize Thunderbolt specific device information
*/
-void mfi_tbolt_init_globals(struct mfi_softc *sc)
+void
+mfi_tbolt_init_globals(struct mfi_softc *sc)
{
/* Initialize single reply size and Message size */
sc->reply_size = MEGASAS_THUNDERBOLT_REPLY_SIZE;
@@ -239,16 +239,12 @@ void mfi_tbolt_init_globals(struct mfi_s
}
/*
- ****************************************************************************
- * Description:
- * This function calculates the memory requirement for Thunderbolt
- * controller
- * Return Value:
- * Total required memory in bytes
- ****************************************************************************
+ * This function calculates the memory requirement for Thunderbolt
+ * controller, returns the total required memory in bytes
*/
-uint32_t mfi_tbolt_get_memory_requirement(struct mfi_softc *sc)
+uint32_t
+mfi_tbolt_get_memory_requirement(struct mfi_softc *sc)
{
uint32_t size;
size = MEGASAS_THUNDERBOLT_MSG_ALLIGNMENT; /* for Alignment */
@@ -260,7 +256,6 @@ uint32_t mfi_tbolt_get_memory_requiremen
}
/*
- ****************************************************************************
* Description:
* This function will prepare message pools for the Thunderbolt controller
* Arguments:
@@ -269,9 +264,9 @@ uint32_t mfi_tbolt_get_memory_requiremen
* Return Value:
* TRUE if successful
* FALSE if failed
- ****************************************************************************
*/
-int mfi_tbolt_init_desc_pool(struct mfi_softc *sc, uint8_t* mem_location,
+int
+mfi_tbolt_init_desc_pool(struct mfi_softc *sc, uint8_t* mem_location,
uint32_t tbolt_contg_length)
{
uint32_t offset = 0;
@@ -328,10 +323,7 @@ int mfi_tbolt_init_desc_pool(struct mfi_
}
/*
- ****************************************************************************
- * Description:
- * This routine prepare and issue INIT2 frame to the Firmware
- ****************************************************************************
+ * This routine prepare and issue INIT2 frame to the Firmware
*/
int
@@ -442,7 +434,8 @@ mfi_tbolt_init_MFI_queue(struct mfi_soft
}
-int mfi_tbolt_alloc_cmd(struct mfi_softc *sc)
+int
+mfi_tbolt_alloc_cmd(struct mfi_softc *sc)
{
struct mfi_cmd_tbolt *cmd;
bus_addr_t io_req_base_phys;
@@ -515,7 +508,8 @@ int mfi_tbolt_alloc_cmd(struct mfi_softc
return 0;
}
-int mfi_tbolt_reset(struct mfi_softc *sc)
+int
+mfi_tbolt_reset(struct mfi_softc *sc)
{
uint32_t fw_state;
@@ -550,7 +544,8 @@ int mfi_tbolt_reset(struct mfi_softc *sc
/*
* mfi_intr_tbolt - isr entry point
*/
-void mfi_intr_tbolt(void *arg)
+void
+mfi_intr_tbolt(void *arg)
{
struct mfi_softc *sc = (struct mfi_softc *)arg;
@@ -568,7 +563,7 @@ void mfi_intr_tbolt(void *arg)
return;
}
-/**
+/*
* map_cmd_status - Maps FW cmd status to OS cmd status
* @cmd : Pointer to cmd
* @status : status of cmd returned by FW
@@ -581,7 +576,6 @@ map_tbolt_cmd_status(struct mfi_command
{
switch (status) {
-
case MFI_STAT_OK:
mfi_cmd->cm_frame->header.cmd_status = 0;
mfi_cmd->cm_frame->dcmd.header.cmd_status = 0;
@@ -614,7 +608,7 @@ map_tbolt_cmd_status(struct mfi_command
}
}
-/**
+/*
* mfi_tbolt_return_cmd - Return a cmd to free command pool
* @instance: Adapter soft state
* @cmd: Command packet to be returned to free command pool
@@ -627,10 +621,11 @@ mfi_tbolt_return_cmd(struct mfi_softc *s
TAILQ_INSERT_TAIL(&sc->mfi_cmd_tbolt_tqh, cmd, next);
}
-void mfi_tbolt_complete_cmd(struct mfi_softc *sc)
+void
+mfi_tbolt_complete_cmd(struct mfi_softc *sc)
{
struct mfi_mpi2_reply_header *desc, *reply_desc;
- struct mfi_command *cmd_mfi; /* For MFA Cmds */
+ struct mfi_command *cmd_mfi, *cmd_mfi_check; /* For MFA Cmds */
struct mfi_cmd_tbolt *cmd_tbolt;
uint16_t smid;
uint8_t reply_descript_type;
@@ -657,7 +652,6 @@ void mfi_tbolt_complete_cmd(struct mfi_s
/* Read Reply descriptor */
while ((val.u.low != 0xFFFFFFFF) && (val.u.high != 0xFFFFFFFF)) {
-
smid = reply_desc->SMID;
if (!smid || smid > sc->mfi_max_fw_cmds + 1) {
device_printf(sc->mfi_dev, "smid is %x. Cannot "
@@ -669,66 +663,20 @@ void mfi_tbolt_complete_cmd(struct mfi_s
cmd_mfi = &sc->mfi_commands[cmd_tbolt->sync_cmd_idx];
scsi_io_req = cmd_tbolt->io_request;
- /* Check if internal commands */
status = cmd_mfi->cm_frame->dcmd.header.cmd_status;
extStatus = cmd_mfi->cm_frame->dcmd.header.scsi_status;
+ map_tbolt_cmd_status(cmd_mfi, status, extStatus);
- switch (scsi_io_req->Function) {
- case MPI2_FUNCTION_LD_IO_REQUEST:
- /* Regular Path IO. */
- /* Map the Fw Error Status. */
- map_tbolt_cmd_status(cmd_mfi, status,
- extStatus);
- if ((cmd_mfi->cm_frame->dcmd.opcode
- == MFI_DCMD_LD_MAP_GET_INFO)
- && (cmd_mfi->cm_frame->dcmd.mbox[1] == 1)) {
- if (cmd_mfi->cm_frame->header.cmd_status
- != 0)
- device_printf(sc->mfi_dev,
- "map sync failed\n");
- else {
- sc->map_id++;
- device_printf(sc->mfi_dev,
- "map sync completed\n");
- mfi_release_command(cmd_mfi);
- }
- }
- if ((cmd_mfi->cm_flags & MFI_ON_MFIQ_BUSY)
- == MFI_ON_MFIQ_BUSY
- && (cmd_mfi->cm_flags & MFI_CMD_POLLED) == 0) {
- /* BHARAT poll workaround */
- mfi_remove_busy(cmd_mfi);
- cmd_mfi->cm_error = 0;
- mfi_complete(sc, cmd_mfi);
- }
- mfi_tbolt_return_cmd(sc, cmd_tbolt);
- break;
- case MPI2_FUNCTION_PASSTHRU_IO_REQUEST:
- map_tbolt_cmd_status(cmd_mfi, status, extStatus);
- if ((cmd_mfi->cm_frame->dcmd.opcode
- == MFI_DCMD_LD_MAP_GET_INFO)
- && (cmd_mfi->cm_frame->dcmd.mbox[1] == 1)) {
- if (cmd_mfi->cm_frame->header.cmd_status != 0)
- device_printf(sc->mfi_dev,
- "map sync failed\n");
- else {
- sc->map_id++;
- device_printf(sc->mfi_dev,
- "map sync completed\n");
- mfi_release_command(cmd_mfi);
- }
- }
- if ((cmd_mfi->cm_flags & MFI_ON_MFIQ_BUSY)
- == MFI_ON_MFIQ_BUSY
- && (cmd_mfi->cm_flags & MFI_CMD_POLLED) == 0) {
- /* BHARAT poll workaround */
+ /* remove command from busy queue if not polled */
+ TAILQ_FOREACH(cmd_mfi_check, &sc->mfi_busy, cm_link) {
+ if (cmd_mfi_check == cmd_mfi) {
mfi_remove_busy(cmd_mfi);
- cmd_mfi->cm_error = 0;
- mfi_complete(sc, cmd_mfi);
+ break;
}
- mfi_tbolt_return_cmd(sc, cmd_tbolt);
- break;
}
+ cmd_mfi->cm_error = 0;
+ mfi_complete(sc, cmd_mfi);
+ mfi_tbolt_return_cmd(sc, cmd_tbolt);
sc->last_reply_idx++;
if (sc->last_reply_idx >= sc->mfi_max_fw_cmds) {
@@ -763,15 +711,15 @@ void mfi_tbolt_complete_cmd(struct mfi_s
return;
}
-/**
+/*
* mfi_get_cmd - Get a command from the free pool
* @instance: Adapter soft state
*
* Returns a free command from the pool
*/
-struct mfi_cmd_tbolt *mfi_tbolt_get_cmd(struct mfi_softc
- *sc)
+struct mfi_cmd_tbolt *
+mfi_tbolt_get_cmd(struct mfi_softc *sc)
{
struct mfi_cmd_tbolt *cmd = NULL;
@@ -876,7 +824,8 @@ mfi_tbolt_build_ldio(struct mfi_softc *s
* MFI_SECTOR_LEN;
}
-int mfi_tbolt_is_ldio(struct mfi_command *mfi_cmd)
+int
+mfi_tbolt_is_ldio(struct mfi_command *mfi_cmd)
{
if (mfi_cmd->cm_frame->header.cmd == MFI_CMD_LD_READ
|| mfi_cmd->cm_frame->header.cmd == MFI_CMD_LD_WRITE)
@@ -886,7 +835,8 @@ int mfi_tbolt_is_ldio(struct mfi_command
}
int
-mfi_tbolt_build_io(struct mfi_softc *sc, struct mfi_command *mfi_cmd, struct mfi_cmd_tbolt *cmd)
+mfi_tbolt_build_io(struct mfi_softc *sc, struct mfi_command *mfi_cmd,
+ struct mfi_cmd_tbolt *cmd)
{
uint32_t device_id;
uint32_t sge_count;
@@ -949,7 +899,7 @@ mfi_tbolt_build_cdb(struct mfi_softc *sc
lba_lo = mfi_cmd->cm_frame->io.lba_lo;
lba_hi = mfi_cmd->cm_frame->io.lba_hi;
- if ((num_lba <= 0xFF) && (lba_lo <= 0x1FFFFF)) {
+ if (lba_hi == 0 && (num_lba <= 0xFF) && (lba_lo <= 0x1FFFFF)) {
if (mfi_cmd->cm_frame->header.cmd == MFI_CMD_LD_WRITE)
/* Read 6 or Write 6 */
cdb[0] = (uint8_t) (0x0A);
@@ -962,7 +912,7 @@ mfi_tbolt_build_cdb(struct mfi_softc *sc
cdb[1] = (uint8_t) ((lba_lo >> 16) & 0x1F);
cdb_len = 6;
}
- else if ((num_lba <= 0xFFFF) && (lba_lo <= 0xFFFFFFFF)) {
+ else if (lba_hi == 0 && (num_lba <= 0xFFFF) && (lba_lo <= 0xFFFFFFFF)) {
if (mfi_cmd->cm_frame->header.cmd == MFI_CMD_LD_WRITE)
/* Read 10 or Write 10 */
cdb[0] = (uint8_t) (0x2A);
@@ -975,8 +925,7 @@ mfi_tbolt_build_cdb(struct mfi_softc *sc
cdb[3] = (uint8_t) (lba_lo >> 16);
cdb[2] = (uint8_t) (lba_lo >> 24);
cdb_len = 10;
- }
- else if ((num_lba > 0xFFFF) && (lba_hi == 0)) {
+ } else if ((num_lba > 0xFFFF) && (lba_hi == 0)) {
if (mfi_cmd->cm_frame->header.cmd == MFI_CMD_LD_WRITE)
/* Read 12 or Write 12 */
cdb[0] = (uint8_t) (0xAA);
@@ -1152,8 +1101,8 @@ mfi_tbolt_send_frame(struct mfi_softc *s
cm->cm_timestamp = time_uptime;
mfi_enqueue_busy(cm);
}
- else {
- hdr->cmd_status = 0xff;
+ else { /* still get interrupts for it */
+ hdr->cmd_status = MFI_STAT_INVALID_STATUS;
hdr->flags |= MFI_FRAME_DONT_POST_IN_REPLY_QUEUE;
}
@@ -1189,22 +1138,23 @@ mfi_tbolt_send_frame(struct mfi_softc *s
return 0;
/* This is a polled command, so busy-wait for it to complete. */
- while (hdr->cmd_status == 0xff) {
+ while (hdr->cmd_status == MFI_STAT_INVALID_STATUS) {
DELAY(1000);
tm -= 1;
if (tm <= 0)
- break;
+ break;
}
- if (hdr->cmd_status == 0xff) {
+ if (hdr->cmd_status == MFI_STAT_INVALID_STATUS) {
device_printf(sc->mfi_dev, "Frame %p timed out "
- "command 0x%X\n", hdr, cm->cm_frame->dcmd.opcode);
+ "command 0x%X\n", hdr, cm->cm_frame->dcmd.opcode);
return (ETIMEDOUT);
}
return 0;
}
-static void mfi_issue_pending_cmds_again (struct mfi_softc *sc)
+static void
+mfi_issue_pending_cmds_again (struct mfi_softc *sc)
{
struct mfi_command *cm, *tmp;
@@ -1249,7 +1199,8 @@ static void mfi_issue_pending_cmds_again
mfi_startio(sc);
}
-static void mfi_kill_hba (struct mfi_softc *sc)
+static void
+mfi_kill_hba (struct mfi_softc *sc)
{
if (sc->mfi_flags & MFI_FLAGS_TBOLT)
MFI_WRITE4 (sc, 0x00,MFI_STOP_ADP);
@@ -1257,7 +1208,8 @@ static void mfi_kill_hba (struct mfi_sof
MFI_WRITE4 (sc, MFI_IDB,MFI_STOP_ADP);
}
-static void mfi_process_fw_state_chg_isr(void *arg)
+static void
+mfi_process_fw_state_chg_isr(void *arg)
{
struct mfi_softc *sc= (struct mfi_softc *)arg;
struct mfi_cmd_tbolt *cmd;
@@ -1308,9 +1260,9 @@ static void mfi_process_fw_state_chg_isr
mfi_release_command(sc->mfi_aen_cm);
sc->mfi_aen_cm = NULL;
}
- if (sc->map_update_cmd) {
- mfi_release_command(sc->map_update_cmd);
- sc->map_update_cmd = NULL;
+ if (sc->mfi_map_sync_cm) {
+ mfi_release_command(sc->mfi_map_sync_cm);
+ sc->mfi_map_sync_cm = NULL;
}
mfi_issue_pending_cmds_again(sc);
@@ -1337,3 +1289,178 @@ static void mfi_process_fw_state_chg_isr
}
mtx_unlock(&sc->mfi_io_lock);
}
+
+/*
+ * The ThunderBolt HW has an option for the driver to directly
+ * access the underlying disks and operate on the RAID. To
+ * do this there needs to be a capability to keep the RAID controller
+ * and driver in sync. The FreeBSD driver does not take advantage
+ * of this feature since it adds a lot of complexity and slows down
+ * performance. Performance is gained by using the controller's
+ * cache etc.
+ *
+ * Even though this driver doesn't access the disks directly, an
+ * AEN like command is used to inform the RAID firmware to "sync"
+ * with all LD's via the MFI_DCMD_LD_MAP_GET_INFO command. This
+ * command in write mode will return when the RAID firmware has
+ * detected a change to the RAID state. Examples of this type
+ * of change are removing a disk. Once the command returns then
+ * the driver needs to acknowledge this and "sync" all LD's again.
+ * This repeats until we shutdown. Then we need to cancel this
+ * pending command.
+ *
+ * If this is not done right the RAID firmware will not remove a
+ * pulled drive and the RAID won't go degraded etc. Effectively,
+ * stopping any RAID mangement to functions.
+ *
+ * Doing another LD sync, requires the use of an event since the
+ * driver needs to do a mfi_wait_command and can't do that in an
+ * interrupt thread.
+ *
+ * The driver could get the RAID state via the MFI_DCMD_LD_MAP_GET_INFO
+ * That requires a bunch of structure and it is simplier to just do
+ * the MFI_DCMD_LD_GET_LIST versus walking the RAID map.
+ */
+
+void
+mfi_tbolt_sync_map_info(struct mfi_softc *sc)
+{
+ int error = 0, i;
+ struct mfi_command *cmd;
+ struct mfi_dcmd_frame *dcmd;
+ uint32_t context = 0;
+ union mfi_ld_ref *ld_sync;
+ size_t ld_size;
+ struct mfi_frame_header *hdr;
+ struct mfi_command *cm = NULL;
+ struct mfi_ld_list *list = NULL;
+
+ if (sc->mfi_map_sync_cm != NULL || sc->cm_map_abort)
+ return;
+
+ mtx_lock(&sc->mfi_io_lock);
+ error = mfi_dcmd_command(sc, &cm, MFI_DCMD_LD_GET_LIST,
+ (void **)&list, sizeof(*list));
+ if (error)
+ goto out;
+
+ cm->cm_flags = MFI_CMD_POLLED | MFI_CMD_DATAIN;
+ if (mfi_wait_command(sc, cm) != 0) {
+ device_printf(sc->mfi_dev, "Failed to get device listing\n");
+ goto out;
+ }
+
+ hdr = &cm->cm_frame->header;
+ if (hdr->cmd_status != MFI_STAT_OK) {
+ device_printf(sc->mfi_dev, "MFI_DCMD_LD_GET_LIST failed %x\n",
+ hdr->cmd_status);
+ goto out;
+ }
+
+ ld_size = sizeof(*ld_sync) * list->ld_count;
+ mtx_unlock(&sc->mfi_io_lock);
+ ld_sync = (union mfi_ld_ref *) malloc(ld_size, M_MFIBUF,
+ M_WAITOK | M_ZERO);
+ if (ld_sync == NULL) {
+ device_printf(sc->mfi_dev, "Failed to allocate sync\n");
+ goto out;
+ }
+ for (i = 0; i < list->ld_count; i++) {
+ ld_sync[i].ref = list->ld_list[i].ld.ref;
+ }
+
+ mtx_lock(&sc->mfi_io_lock);
+ if ((cmd = mfi_dequeue_free(sc)) == NULL) {
+ device_printf(sc->mfi_dev, "Failed to get command\n");
+ free(ld_sync, M_MFIBUF);
+ goto out;
+ }
+
+ context = cmd->cm_frame->header.context;
+ bzero(cmd->cm_frame, sizeof(union mfi_frame));
+ cmd->cm_frame->header.context = context;
+
+ dcmd = &cmd->cm_frame->dcmd;
+ bzero(dcmd->mbox, MFI_MBOX_SIZE);
+ dcmd->header.cmd = MFI_CMD_DCMD;
+ dcmd->header.flags = MFI_FRAME_DIR_WRITE;
+ dcmd->header.timeout = 0;
+ dcmd->header.data_len = ld_size;
+ dcmd->header.scsi_status = 0;
+ dcmd->opcode = MFI_DCMD_LD_MAP_GET_INFO;
+ cmd->cm_sg = &dcmd->sgl;
+ cmd->cm_total_frame_size = MFI_DCMD_FRAME_SIZE;
+ cmd->cm_data = ld_sync;
+ cmd->cm_private = ld_sync;
+
+ cmd->cm_len = ld_size;
+ cmd->cm_complete = mfi_sync_map_complete;
+ sc->mfi_map_sync_cm = cmd;
+
+ cmd->cm_flags = MFI_CMD_DATAOUT;
+ cmd->cm_frame->dcmd.mbox[0] = list->ld_count;
+ cmd->cm_frame->dcmd.mbox[1] = MFI_DCMD_MBOX_PEND_FLAG;
+
+ if ((error = mfi_mapcmd(sc, cmd)) != 0) {
+ device_printf(sc->mfi_dev, "failed to send map sync\n");
+ free(ld_sync, M_MFIBUF);
+ sc->mfi_map_sync_cm = NULL;
+ mfi_requeue_ready(cmd);
+ goto out;
+ }
+
+out:
+ if (list)
+ free(list, M_MFIBUF);
+ if (cm)
+ mfi_release_command(cm);
+ mtx_unlock(&sc->mfi_io_lock);
+}
+
+static void
+mfi_sync_map_complete(struct mfi_command *cm)
+{
+ struct mfi_frame_header *hdr;
+ struct mfi_softc *sc;
+ int aborted = 0;
+
+ sc = cm->cm_sc;
+ mtx_assert(&sc->mfi_io_lock, MA_OWNED);
+
+ hdr = &cm->cm_frame->header;
+
+ if (sc->mfi_map_sync_cm == NULL)
+ return;
+
+ if (sc->cm_map_abort ||
+ hdr->cmd_status == MFI_STAT_INVALID_STATUS) {
+ sc->cm_map_abort = 0;
+ aborted = 1;
+ }
+
+ free(cm->cm_data, M_MFIBUF);
+ sc->mfi_map_sync_cm = NULL;
+ wakeup(&sc->mfi_map_sync_cm);
+ mfi_release_command(cm);
+
+ /* set it up again so the driver can catch more events */
+ if (!aborted) {
+ mfi_queue_map_sync(sc);
+ }
+}
+
+static void
+mfi_queue_map_sync(struct mfi_softc *sc)
+{
+ mtx_assert(&sc->mfi_io_lock, MA_OWNED);
+ taskqueue_enqueue(taskqueue_swi, &sc->mfi_map_sync_task);
+}
+
+void
+mfi_handle_map_sync(void *context, int pending)
+{
+ struct mfi_softc *sc;
+
+ sc = context;
+ mfi_tbolt_sync_map_info(sc);
+}
Modified: stable/9/sys/dev/mfi/mfireg.h
==============================================================================
--- stable/9/sys/dev/mfi/mfireg.h Mon May 7 18:30:22 2012 (r235134)
+++ stable/9/sys/dev/mfi/mfireg.h Mon May 7 19:17:09 2012 (r235135)
@@ -403,6 +403,7 @@ typedef enum {
#define MR_EVT_CTRL_HOST_BUS_SCAN_REQUESTED 0x0152
#define MR_EVT_PD_REMOVED 0x0070
#define MR_EVT_PD_INSERTED 0x005b
+#define MR_EVT_LD_CHANGE 0x0051
typedef enum {
MR_LD_CACHE_WRITE_BACK = 0x01,
Modified: stable/9/sys/dev/mfi/mfivar.h
==============================================================================
--- stable/9/sys/dev/mfi/mfivar.h Mon May 7 18:30:22 2012 (r235134)
+++ stable/9/sys/dev/mfi/mfivar.h Mon May 7 19:17:09 2012 (r235135)
@@ -105,7 +105,6 @@ struct mfi_command {
#define MFI_ON_MFIQ_READY (1<<6)
#define MFI_ON_MFIQ_BUSY (1<<7)
#define MFI_ON_MFIQ_MASK ((1<<5)|(1<<6)|(1<<7))
- int cm_aen_abort;
uint8_t retry_for_fw_reset;
void (* cm_complete)(struct mfi_command *cm);
void *cm_private;
@@ -216,9 +215,13 @@ struct mfi_softc {
TAILQ_HEAD(,mfi_evt_queue_elm) mfi_evt_queue;
struct task mfi_evt_task;
+ struct task mfi_map_sync_task;
TAILQ_HEAD(,mfi_aen) mfi_aen_pids;
struct mfi_command *mfi_aen_cm;
struct mfi_command *mfi_skinny_cm;
+ struct mfi_command *mfi_map_sync_cm;
+ int cm_aen_abort;
+ int cm_map_abort;
uint32_t mfi_aen_triggered;
uint32_t mfi_poll_waiting;
uint32_t mfi_boot_seq_num;
@@ -303,8 +306,6 @@ struct mfi_softc {
/* ThunderBolt */
uint32_t mfi_tbolt;
uint32_t MFA_enabled;
- uint64_t map_id;
- struct mfi_command *map_update_cmd;
/* Single Reply structure size */
uint16_t reply_size;
/* Singler message size. */
@@ -417,7 +418,10 @@ extern int mfi_tbolt_alloc_cmd(struct mf
extern int mfi_tbolt_send_frame(struct mfi_softc *sc, struct mfi_command *cm);
extern int mfi_tbolt_adp_reset(struct mfi_softc *sc);
extern int mfi_tbolt_reset(struct mfi_softc *sc);
-extern int mfi_tbolt_sync_map_info(struct mfi_softc *sc);
+extern void mfi_tbolt_sync_map_info(struct mfi_softc *sc);
+extern void mfi_handle_map_sync(void *context, int pending);
+extern int mfi_dcmd_command(struct mfi_softc *, struct mfi_command **,
+ uint32_t, void **, size_t);
#define MFIQ_ADD(sc, qname) \
do { \
More information about the svn-src-stable-9
mailing list