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 {                                                    \
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to