12ffc8bcaSDan McDonald /*
22ffc8bcaSDan McDonald * mr_sas_tbolt.c: source for mr_sas driver for New Generation.
32ffc8bcaSDan McDonald * i.e. Thunderbolt and Invader
42ffc8bcaSDan McDonald *
52ffc8bcaSDan McDonald * Solaris MegaRAID device driver for SAS2.0 controllers
62ffc8bcaSDan McDonald * Copyright (c) 2008-2012, LSI Logic Corporation.
72ffc8bcaSDan McDonald * All rights reserved.
82ffc8bcaSDan McDonald *
92ffc8bcaSDan McDonald * Version:
102ffc8bcaSDan McDonald * Author:
112ffc8bcaSDan McDonald * Swaminathan K S
122ffc8bcaSDan McDonald * Arun Chandrashekhar
132ffc8bcaSDan McDonald * Manju R
142ffc8bcaSDan McDonald * Rasheed
152ffc8bcaSDan McDonald * Shakeel Bukhari
162ffc8bcaSDan McDonald */
172ffc8bcaSDan McDonald
18a1c36c8bSDan McDonald /*
19d8873b31SJoyce McIntosh * Copyright 2018 Nexenta Systems, Inc.
20df950592SHummyPkg * Copyright 2015, 2017 Citrus IT Limited. All rights reserved.
21a1ed883aSGarrett D'Amore * Copyright 2015 Garrett D'Amore <garrett@damore.org>
22a1c36c8bSDan McDonald */
23a1c36c8bSDan McDonald
242ffc8bcaSDan McDonald
252ffc8bcaSDan McDonald #include <sys/types.h>
262ffc8bcaSDan McDonald #include <sys/file.h>
272ffc8bcaSDan McDonald #include <sys/atomic.h>
282ffc8bcaSDan McDonald #include <sys/scsi/scsi.h>
292ffc8bcaSDan McDonald #include <sys/byteorder.h>
30091932b4SAndy Fiddaman #include <sys/sdt.h>
312ffc8bcaSDan McDonald #include "ld_pd_map.h"
322ffc8bcaSDan McDonald #include "mr_sas.h"
332ffc8bcaSDan McDonald #include "fusion.h"
342ffc8bcaSDan McDonald
352ffc8bcaSDan McDonald /*
362ffc8bcaSDan McDonald * FMA header files
372ffc8bcaSDan McDonald */
382ffc8bcaSDan McDonald #include <sys/ddifm.h>
392ffc8bcaSDan McDonald #include <sys/fm/protocol.h>
402ffc8bcaSDan McDonald #include <sys/fm/util.h>
412ffc8bcaSDan McDonald #include <sys/fm/io/ddi.h>
422ffc8bcaSDan McDonald
432ffc8bcaSDan McDonald
442ffc8bcaSDan McDonald /* Pre-TB command size and TB command size. */
452ffc8bcaSDan McDonald #define MR_COMMAND_SIZE (64*20) /* 1280 bytes */
462ffc8bcaSDan McDonald MR_LD_RAID *MR_LdRaidGet(U32 ld, MR_FW_RAID_MAP_ALL *map);
472ffc8bcaSDan McDonald U16 MR_TargetIdToLdGet(U32 ldTgtId, MR_FW_RAID_MAP_ALL *map);
482ffc8bcaSDan McDonald U16 MR_GetLDTgtId(U32 ld, MR_FW_RAID_MAP_ALL *map);
492ffc8bcaSDan McDonald U16 get_updated_dev_handle(PLD_LOAD_BALANCE_INFO, struct IO_REQUEST_INFO *);
502ffc8bcaSDan McDonald extern ddi_dma_attr_t mrsas_generic_dma_attr;
512ffc8bcaSDan McDonald extern uint32_t mrsas_tbolt_max_cap_maxxfer;
522ffc8bcaSDan McDonald extern struct ddi_device_acc_attr endian_attr;
532ffc8bcaSDan McDonald extern int debug_level_g;
542ffc8bcaSDan McDonald extern unsigned int enable_fp;
55d8873b31SJoyce McIntosh volatile int dump_io_wait_time = 900;
562ffc8bcaSDan McDonald extern volatile int debug_timeout_g;
572ffc8bcaSDan McDonald extern int mrsas_issue_pending_cmds(struct mrsas_instance *);
582ffc8bcaSDan McDonald extern int mrsas_complete_pending_cmds(struct mrsas_instance *instance);
592ffc8bcaSDan McDonald extern void push_pending_mfi_pkt(struct mrsas_instance *,
602ffc8bcaSDan McDonald struct mrsas_cmd *);
612ffc8bcaSDan McDonald extern U8 MR_BuildRaidContext(struct mrsas_instance *, struct IO_REQUEST_INFO *,
622ffc8bcaSDan McDonald MPI2_SCSI_IO_VENDOR_UNIQUE *, MR_FW_RAID_MAP_ALL *);
632ffc8bcaSDan McDonald
642ffc8bcaSDan McDonald /* Local static prototypes. */
652ffc8bcaSDan McDonald static struct mrsas_cmd *mrsas_tbolt_build_cmd(struct mrsas_instance *,
662ffc8bcaSDan McDonald struct scsi_address *, struct scsi_pkt *, uchar_t *);
673344ffb7SToomas Soome static void mrsas_tbolt_set_pd_lba(U8 *, size_t, uint8_t *, U64, U32);
682ffc8bcaSDan McDonald static int mrsas_tbolt_check_map_info(struct mrsas_instance *);
692ffc8bcaSDan McDonald static int mrsas_tbolt_sync_map_info(struct mrsas_instance *);
702ffc8bcaSDan McDonald static int mrsas_tbolt_prepare_pkt(struct scsa_cmd *);
712ffc8bcaSDan McDonald static int mrsas_tbolt_ioc_init(struct mrsas_instance *, dma_obj_t *);
722ffc8bcaSDan McDonald static void mrsas_tbolt_get_pd_info(struct mrsas_instance *,
732ffc8bcaSDan McDonald struct mrsas_tbolt_pd_info *, int);
742ffc8bcaSDan McDonald
75eef6dbdfSAndy Fiddaman static int mrsas_debug_tbolt_fw_faults_after_ocr = 0;
762ffc8bcaSDan McDonald
772ffc8bcaSDan McDonald /*
782ffc8bcaSDan McDonald * destroy_mfi_mpi_frame_pool
792ffc8bcaSDan McDonald */
802ffc8bcaSDan McDonald void
destroy_mfi_mpi_frame_pool(struct mrsas_instance * instance)812ffc8bcaSDan McDonald destroy_mfi_mpi_frame_pool(struct mrsas_instance *instance)
822ffc8bcaSDan McDonald {
832ffc8bcaSDan McDonald int i;
842ffc8bcaSDan McDonald
852ffc8bcaSDan McDonald struct mrsas_cmd *cmd;
862ffc8bcaSDan McDonald
872ffc8bcaSDan McDonald /* return all mfi frames to pool */
882ffc8bcaSDan McDonald for (i = 0; i < MRSAS_APP_RESERVED_CMDS; i++) {
892ffc8bcaSDan McDonald cmd = instance->cmd_list[i];
902ffc8bcaSDan McDonald if (cmd->frame_dma_obj_status == DMA_OBJ_ALLOCATED) {
912ffc8bcaSDan McDonald (void) mrsas_free_dma_obj(instance,
922ffc8bcaSDan McDonald cmd->frame_dma_obj);
932ffc8bcaSDan McDonald }
942ffc8bcaSDan McDonald cmd->frame_dma_obj_status = DMA_OBJ_FREED;
952ffc8bcaSDan McDonald }
962ffc8bcaSDan McDonald }
972ffc8bcaSDan McDonald
982ffc8bcaSDan McDonald /*
992ffc8bcaSDan McDonald * destroy_mpi2_frame_pool
1002ffc8bcaSDan McDonald */
1012ffc8bcaSDan McDonald void
destroy_mpi2_frame_pool(struct mrsas_instance * instance)1022ffc8bcaSDan McDonald destroy_mpi2_frame_pool(struct mrsas_instance *instance)
1032ffc8bcaSDan McDonald {
1042ffc8bcaSDan McDonald
1052ffc8bcaSDan McDonald if (instance->mpi2_frame_pool_dma_obj.status == DMA_OBJ_ALLOCATED) {
1062ffc8bcaSDan McDonald (void) mrsas_free_dma_obj(instance,
1072ffc8bcaSDan McDonald instance->mpi2_frame_pool_dma_obj);
1082ffc8bcaSDan McDonald instance->mpi2_frame_pool_dma_obj.status |= DMA_OBJ_FREED;
1092ffc8bcaSDan McDonald }
1102ffc8bcaSDan McDonald }
1112ffc8bcaSDan McDonald
1122ffc8bcaSDan McDonald
1132ffc8bcaSDan McDonald /*
1142ffc8bcaSDan McDonald * mrsas_tbolt_free_additional_dma_buffer
1152ffc8bcaSDan McDonald */
1162ffc8bcaSDan McDonald void
mrsas_tbolt_free_additional_dma_buffer(struct mrsas_instance * instance)1172ffc8bcaSDan McDonald mrsas_tbolt_free_additional_dma_buffer(struct mrsas_instance *instance)
1182ffc8bcaSDan McDonald {
1192ffc8bcaSDan McDonald int i;
1202ffc8bcaSDan McDonald
1212ffc8bcaSDan McDonald if (instance->mfi_internal_dma_obj.status == DMA_OBJ_ALLOCATED) {
1222ffc8bcaSDan McDonald (void) mrsas_free_dma_obj(instance,
1232ffc8bcaSDan McDonald instance->mfi_internal_dma_obj);
1242ffc8bcaSDan McDonald instance->mfi_internal_dma_obj.status = DMA_OBJ_FREED;
1252ffc8bcaSDan McDonald }
1262ffc8bcaSDan McDonald if (instance->mfi_evt_detail_obj.status == DMA_OBJ_ALLOCATED) {
1272ffc8bcaSDan McDonald (void) mrsas_free_dma_obj(instance,
1282ffc8bcaSDan McDonald instance->mfi_evt_detail_obj);
1292ffc8bcaSDan McDonald instance->mfi_evt_detail_obj.status = DMA_OBJ_FREED;
1302ffc8bcaSDan McDonald }
1312ffc8bcaSDan McDonald
1322ffc8bcaSDan McDonald for (i = 0; i < 2; i++) {
1332ffc8bcaSDan McDonald if (instance->ld_map_obj[i].status == DMA_OBJ_ALLOCATED) {
1342ffc8bcaSDan McDonald (void) mrsas_free_dma_obj(instance,
1352ffc8bcaSDan McDonald instance->ld_map_obj[i]);
1362ffc8bcaSDan McDonald instance->ld_map_obj[i].status = DMA_OBJ_FREED;
1372ffc8bcaSDan McDonald }
1382ffc8bcaSDan McDonald }
1392ffc8bcaSDan McDonald }
1402ffc8bcaSDan McDonald
1412ffc8bcaSDan McDonald
1422ffc8bcaSDan McDonald /*
1432ffc8bcaSDan McDonald * free_req_desc_pool
1442ffc8bcaSDan McDonald */
1452ffc8bcaSDan McDonald void
free_req_rep_desc_pool(struct mrsas_instance * instance)1462ffc8bcaSDan McDonald free_req_rep_desc_pool(struct mrsas_instance *instance)
1472ffc8bcaSDan McDonald {
1482ffc8bcaSDan McDonald if (instance->request_desc_dma_obj.status == DMA_OBJ_ALLOCATED) {
1492ffc8bcaSDan McDonald (void) mrsas_free_dma_obj(instance,
1502ffc8bcaSDan McDonald instance->request_desc_dma_obj);
1512ffc8bcaSDan McDonald instance->request_desc_dma_obj.status = DMA_OBJ_FREED;
1522ffc8bcaSDan McDonald }
1532ffc8bcaSDan McDonald
1542ffc8bcaSDan McDonald if (instance->reply_desc_dma_obj.status == DMA_OBJ_ALLOCATED) {
1552ffc8bcaSDan McDonald (void) mrsas_free_dma_obj(instance,
1562ffc8bcaSDan McDonald instance->reply_desc_dma_obj);
1572ffc8bcaSDan McDonald instance->reply_desc_dma_obj.status = DMA_OBJ_FREED;
1582ffc8bcaSDan McDonald }
1592ffc8bcaSDan McDonald
1602ffc8bcaSDan McDonald
1612ffc8bcaSDan McDonald }
1622ffc8bcaSDan McDonald
1632ffc8bcaSDan McDonald
1642ffc8bcaSDan McDonald /*
1652ffc8bcaSDan McDonald * ThunderBolt(TB) Request Message Frame Pool
1662ffc8bcaSDan McDonald */
1672ffc8bcaSDan McDonald int
create_mpi2_frame_pool(struct mrsas_instance * instance)1682ffc8bcaSDan McDonald create_mpi2_frame_pool(struct mrsas_instance *instance)
1692ffc8bcaSDan McDonald {
1702ffc8bcaSDan McDonald int i = 0;
1712ffc8bcaSDan McDonald uint16_t max_cmd;
1722ffc8bcaSDan McDonald uint32_t sgl_sz;
1732ffc8bcaSDan McDonald uint32_t raid_msg_size;
1742ffc8bcaSDan McDonald uint32_t total_size;
1752ffc8bcaSDan McDonald uint32_t offset;
1762ffc8bcaSDan McDonald uint32_t io_req_base_phys;
1772ffc8bcaSDan McDonald uint8_t *io_req_base;
1782ffc8bcaSDan McDonald struct mrsas_cmd *cmd;
1792ffc8bcaSDan McDonald
1802ffc8bcaSDan McDonald max_cmd = instance->max_fw_cmds;
1812ffc8bcaSDan McDonald
1822ffc8bcaSDan McDonald sgl_sz = 1024;
1832ffc8bcaSDan McDonald raid_msg_size = MRSAS_THUNDERBOLT_MSG_SIZE;
1842ffc8bcaSDan McDonald
1852ffc8bcaSDan McDonald /* Allocating additional 256 bytes to accomodate SMID 0. */
1862ffc8bcaSDan McDonald total_size = MRSAS_THUNDERBOLT_MSG_SIZE + (max_cmd * raid_msg_size) +
1872ffc8bcaSDan McDonald (max_cmd * sgl_sz) + (max_cmd * SENSE_LENGTH);
1882ffc8bcaSDan McDonald
1892ffc8bcaSDan McDonald con_log(CL_ANN1, (CE_NOTE, "create_mpi2_frame_pool: "
1902ffc8bcaSDan McDonald "max_cmd %x", max_cmd));
1912ffc8bcaSDan McDonald
1922ffc8bcaSDan McDonald con_log(CL_DLEVEL3, (CE_NOTE, "create_mpi2_frame_pool: "
1932ffc8bcaSDan McDonald "request message frame pool size %x", total_size));
1942ffc8bcaSDan McDonald
1952ffc8bcaSDan McDonald /*
1962ffc8bcaSDan McDonald * ThunderBolt(TB) We need to create a single chunk of DMA'ble memory
1972ffc8bcaSDan McDonald * and then split the memory to 1024 commands. Each command should be
1982ffc8bcaSDan McDonald * able to contain a RAID MESSAGE FRAME which will embed a MFI_FRAME
1992ffc8bcaSDan McDonald * within it. Further refer the "alloc_req_rep_desc" function where
2002ffc8bcaSDan McDonald * we allocate request/reply descriptors queues for a clue.
2012ffc8bcaSDan McDonald */
2022ffc8bcaSDan McDonald
2032ffc8bcaSDan McDonald instance->mpi2_frame_pool_dma_obj.size = total_size;
2042ffc8bcaSDan McDonald instance->mpi2_frame_pool_dma_obj.dma_attr = mrsas_generic_dma_attr;
2052ffc8bcaSDan McDonald instance->mpi2_frame_pool_dma_obj.dma_attr.dma_attr_addr_hi =
2062ffc8bcaSDan McDonald 0xFFFFFFFFU;
2072ffc8bcaSDan McDonald instance->mpi2_frame_pool_dma_obj.dma_attr.dma_attr_count_max =
2082ffc8bcaSDan McDonald 0xFFFFFFFFU;
2092ffc8bcaSDan McDonald instance->mpi2_frame_pool_dma_obj.dma_attr.dma_attr_sgllen = 1;
2102ffc8bcaSDan McDonald instance->mpi2_frame_pool_dma_obj.dma_attr.dma_attr_align = 256;
2112ffc8bcaSDan McDonald
2122ffc8bcaSDan McDonald if (mrsas_alloc_dma_obj(instance, &instance->mpi2_frame_pool_dma_obj,
2132ffc8bcaSDan McDonald (uchar_t)DDI_STRUCTURE_LE_ACC) != 1) {
214ff38cf9dSAndy Fiddaman dev_err(instance->dip, CE_WARN,
215ff38cf9dSAndy Fiddaman "could not alloc mpi2 frame pool");
2162ffc8bcaSDan McDonald return (DDI_FAILURE);
2172ffc8bcaSDan McDonald }
2182ffc8bcaSDan McDonald
2192ffc8bcaSDan McDonald bzero(instance->mpi2_frame_pool_dma_obj.buffer, total_size);
2202ffc8bcaSDan McDonald instance->mpi2_frame_pool_dma_obj.status |= DMA_OBJ_ALLOCATED;
2212ffc8bcaSDan McDonald
2222ffc8bcaSDan McDonald instance->io_request_frames =
2232ffc8bcaSDan McDonald (uint8_t *)instance->mpi2_frame_pool_dma_obj.buffer;
2242ffc8bcaSDan McDonald instance->io_request_frames_phy =
2252ffc8bcaSDan McDonald (uint32_t)
2262ffc8bcaSDan McDonald instance->mpi2_frame_pool_dma_obj.dma_cookie[0].dmac_address;
2272ffc8bcaSDan McDonald
2282ffc8bcaSDan McDonald con_log(CL_DLEVEL3, (CE_NOTE, "io_request_frames 0x%p",
2292ffc8bcaSDan McDonald (void *)instance->io_request_frames));
2302ffc8bcaSDan McDonald
2312ffc8bcaSDan McDonald con_log(CL_DLEVEL3, (CE_NOTE, "io_request_frames_phy 0x%x",
2322ffc8bcaSDan McDonald instance->io_request_frames_phy));
2332ffc8bcaSDan McDonald
2342ffc8bcaSDan McDonald io_req_base = (uint8_t *)instance->io_request_frames +
2352ffc8bcaSDan McDonald MRSAS_THUNDERBOLT_MSG_SIZE;
2362ffc8bcaSDan McDonald io_req_base_phys = instance->io_request_frames_phy +
2372ffc8bcaSDan McDonald MRSAS_THUNDERBOLT_MSG_SIZE;
2382ffc8bcaSDan McDonald
2392ffc8bcaSDan McDonald con_log(CL_DLEVEL3, (CE_NOTE,
2402ffc8bcaSDan McDonald "io req_base_phys 0x%x", io_req_base_phys));
2412ffc8bcaSDan McDonald
2422ffc8bcaSDan McDonald for (i = 0; i < max_cmd; i++) {
2432ffc8bcaSDan McDonald cmd = instance->cmd_list[i];
2442ffc8bcaSDan McDonald
2452ffc8bcaSDan McDonald offset = i * MRSAS_THUNDERBOLT_MSG_SIZE;
2462ffc8bcaSDan McDonald
2472ffc8bcaSDan McDonald cmd->scsi_io_request = (Mpi2RaidSCSIIORequest_t *)
2482ffc8bcaSDan McDonald ((uint8_t *)io_req_base + offset);
2492ffc8bcaSDan McDonald cmd->scsi_io_request_phys_addr = io_req_base_phys + offset;
2502ffc8bcaSDan McDonald
2512ffc8bcaSDan McDonald cmd->sgl = (Mpi2SGEIOUnion_t *)((uint8_t *)io_req_base +
2522ffc8bcaSDan McDonald (max_cmd * raid_msg_size) + i * sgl_sz);
2532ffc8bcaSDan McDonald
2542ffc8bcaSDan McDonald cmd->sgl_phys_addr = (io_req_base_phys +
2552ffc8bcaSDan McDonald (max_cmd * raid_msg_size) + i * sgl_sz);
2562ffc8bcaSDan McDonald
2572ffc8bcaSDan McDonald cmd->sense1 = (uint8_t *)((uint8_t *)io_req_base +
2582ffc8bcaSDan McDonald (max_cmd * raid_msg_size) + (max_cmd * sgl_sz) +
2592ffc8bcaSDan McDonald (i * SENSE_LENGTH));
2602ffc8bcaSDan McDonald
2612ffc8bcaSDan McDonald cmd->sense_phys_addr1 = (io_req_base_phys +
2622ffc8bcaSDan McDonald (max_cmd * raid_msg_size) + (max_cmd * sgl_sz) +
2632ffc8bcaSDan McDonald (i * SENSE_LENGTH));
2642ffc8bcaSDan McDonald
2652ffc8bcaSDan McDonald
2662ffc8bcaSDan McDonald cmd->SMID = i + 1;
2672ffc8bcaSDan McDonald
2682ffc8bcaSDan McDonald con_log(CL_DLEVEL3, (CE_NOTE, "Frame Pool Addr [%x]0x%p",
2692ffc8bcaSDan McDonald cmd->index, (void *)cmd->scsi_io_request));
2702ffc8bcaSDan McDonald
2712ffc8bcaSDan McDonald con_log(CL_DLEVEL3, (CE_NOTE, "Frame Pool Phys Addr [%x]0x%x",
2722ffc8bcaSDan McDonald cmd->index, cmd->scsi_io_request_phys_addr));
2732ffc8bcaSDan McDonald
2742ffc8bcaSDan McDonald con_log(CL_DLEVEL3, (CE_NOTE, "Sense Addr [%x]0x%p",
2752ffc8bcaSDan McDonald cmd->index, (void *)cmd->sense1));
2762ffc8bcaSDan McDonald
2772ffc8bcaSDan McDonald con_log(CL_DLEVEL3, (CE_NOTE, "Sense Addr Phys [%x]0x%x",
2782ffc8bcaSDan McDonald cmd->index, cmd->sense_phys_addr1));
2792ffc8bcaSDan McDonald
2802ffc8bcaSDan McDonald con_log(CL_DLEVEL3, (CE_NOTE, "Sgl bufffers [%x]0x%p",
2812ffc8bcaSDan McDonald cmd->index, (void *)cmd->sgl));
2822ffc8bcaSDan McDonald
2832ffc8bcaSDan McDonald con_log(CL_DLEVEL3, (CE_NOTE, "Sgl bufffers phys [%x]0x%x",
2842ffc8bcaSDan McDonald cmd->index, cmd->sgl_phys_addr));
2852ffc8bcaSDan McDonald }
2862ffc8bcaSDan McDonald
2872ffc8bcaSDan McDonald return (DDI_SUCCESS);
2882ffc8bcaSDan McDonald
2892ffc8bcaSDan McDonald }
2902ffc8bcaSDan McDonald
2912ffc8bcaSDan McDonald
2922ffc8bcaSDan McDonald /*
2932ffc8bcaSDan McDonald * alloc_additional_dma_buffer for AEN
2942ffc8bcaSDan McDonald */
2952ffc8bcaSDan McDonald int
mrsas_tbolt_alloc_additional_dma_buffer(struct mrsas_instance * instance)2962ffc8bcaSDan McDonald mrsas_tbolt_alloc_additional_dma_buffer(struct mrsas_instance *instance)
2972ffc8bcaSDan McDonald {
2982ffc8bcaSDan McDonald uint32_t internal_buf_size = PAGESIZE*2;
2992ffc8bcaSDan McDonald int i;
3002ffc8bcaSDan McDonald
3012ffc8bcaSDan McDonald /* Initialize buffer status as free */
3022ffc8bcaSDan McDonald instance->mfi_internal_dma_obj.status = DMA_OBJ_FREED;
3032ffc8bcaSDan McDonald instance->mfi_evt_detail_obj.status = DMA_OBJ_FREED;
3042ffc8bcaSDan McDonald instance->ld_map_obj[0].status = DMA_OBJ_FREED;
3052ffc8bcaSDan McDonald instance->ld_map_obj[1].status = DMA_OBJ_FREED;
3062ffc8bcaSDan McDonald
3072ffc8bcaSDan McDonald
3082ffc8bcaSDan McDonald instance->mfi_internal_dma_obj.size = internal_buf_size;
3092ffc8bcaSDan McDonald instance->mfi_internal_dma_obj.dma_attr = mrsas_generic_dma_attr;
3102ffc8bcaSDan McDonald instance->mfi_internal_dma_obj.dma_attr.dma_attr_addr_hi = 0xFFFFFFFFU;
3112ffc8bcaSDan McDonald instance->mfi_internal_dma_obj.dma_attr.dma_attr_count_max =
3122ffc8bcaSDan McDonald 0xFFFFFFFFU;
3132ffc8bcaSDan McDonald instance->mfi_internal_dma_obj.dma_attr.dma_attr_sgllen = 1;
3142ffc8bcaSDan McDonald
3152ffc8bcaSDan McDonald if (mrsas_alloc_dma_obj(instance, &instance->mfi_internal_dma_obj,
3162ffc8bcaSDan McDonald (uchar_t)DDI_STRUCTURE_LE_ACC) != 1) {
317ff38cf9dSAndy Fiddaman dev_err(instance->dip, CE_WARN,
318ff38cf9dSAndy Fiddaman "could not alloc reply queue");
3192ffc8bcaSDan McDonald return (DDI_FAILURE);
3202ffc8bcaSDan McDonald }
3212ffc8bcaSDan McDonald
3222ffc8bcaSDan McDonald bzero(instance->mfi_internal_dma_obj.buffer, internal_buf_size);
3232ffc8bcaSDan McDonald
3242ffc8bcaSDan McDonald instance->mfi_internal_dma_obj.status |= DMA_OBJ_ALLOCATED;
3252ffc8bcaSDan McDonald instance->internal_buf =
3262ffc8bcaSDan McDonald (caddr_t)(((unsigned long)instance->mfi_internal_dma_obj.buffer));
3272ffc8bcaSDan McDonald instance->internal_buf_dmac_add =
3282ffc8bcaSDan McDonald instance->mfi_internal_dma_obj.dma_cookie[0].dmac_address;
3292ffc8bcaSDan McDonald instance->internal_buf_size = internal_buf_size;
3302ffc8bcaSDan McDonald
3312ffc8bcaSDan McDonald /* allocate evt_detail */
3322ffc8bcaSDan McDonald instance->mfi_evt_detail_obj.size = sizeof (struct mrsas_evt_detail);
3332ffc8bcaSDan McDonald instance->mfi_evt_detail_obj.dma_attr = mrsas_generic_dma_attr;
3342ffc8bcaSDan McDonald instance->mfi_evt_detail_obj.dma_attr.dma_attr_addr_hi = 0xFFFFFFFFU;
3352ffc8bcaSDan McDonald instance->mfi_evt_detail_obj.dma_attr.dma_attr_count_max = 0xFFFFFFFFU;
3362ffc8bcaSDan McDonald instance->mfi_evt_detail_obj.dma_attr.dma_attr_sgllen = 1;
3372ffc8bcaSDan McDonald instance->mfi_evt_detail_obj.dma_attr.dma_attr_align = 8;
3382ffc8bcaSDan McDonald
3392ffc8bcaSDan McDonald if (mrsas_alloc_dma_obj(instance, &instance->mfi_evt_detail_obj,
3402ffc8bcaSDan McDonald (uchar_t)DDI_STRUCTURE_LE_ACC) != 1) {
341ff38cf9dSAndy Fiddaman dev_err(instance->dip, CE_WARN,
342ff38cf9dSAndy Fiddaman "mrsas_tbolt_alloc_additional_dma_buffer: "
3432ffc8bcaSDan McDonald "could not allocate data transfer buffer.");
3442ffc8bcaSDan McDonald goto fail_tbolt_additional_buff;
3452ffc8bcaSDan McDonald }
3462ffc8bcaSDan McDonald
3472ffc8bcaSDan McDonald bzero(instance->mfi_evt_detail_obj.buffer,
3482ffc8bcaSDan McDonald sizeof (struct mrsas_evt_detail));
3492ffc8bcaSDan McDonald
3502ffc8bcaSDan McDonald instance->mfi_evt_detail_obj.status |= DMA_OBJ_ALLOCATED;
3512ffc8bcaSDan McDonald
3522ffc8bcaSDan McDonald instance->size_map_info = sizeof (MR_FW_RAID_MAP) +
3532ffc8bcaSDan McDonald (sizeof (MR_LD_SPAN_MAP) * (MAX_LOGICAL_DRIVES - 1));
3542ffc8bcaSDan McDonald
3552ffc8bcaSDan McDonald for (i = 0; i < 2; i++) {
3562ffc8bcaSDan McDonald /* allocate the data transfer buffer */
3572ffc8bcaSDan McDonald instance->ld_map_obj[i].size = instance->size_map_info;
3582ffc8bcaSDan McDonald instance->ld_map_obj[i].dma_attr = mrsas_generic_dma_attr;
3592ffc8bcaSDan McDonald instance->ld_map_obj[i].dma_attr.dma_attr_addr_hi = 0xFFFFFFFFU;
3602ffc8bcaSDan McDonald instance->ld_map_obj[i].dma_attr.dma_attr_count_max =
3612ffc8bcaSDan McDonald 0xFFFFFFFFU;
3622ffc8bcaSDan McDonald instance->ld_map_obj[i].dma_attr.dma_attr_sgllen = 1;
3632ffc8bcaSDan McDonald instance->ld_map_obj[i].dma_attr.dma_attr_align = 1;
3642ffc8bcaSDan McDonald
3652ffc8bcaSDan McDonald if (mrsas_alloc_dma_obj(instance, &instance->ld_map_obj[i],
3662ffc8bcaSDan McDonald (uchar_t)DDI_STRUCTURE_LE_ACC) != 1) {
367ff38cf9dSAndy Fiddaman dev_err(instance->dip, CE_WARN,
3682ffc8bcaSDan McDonald "could not allocate data transfer buffer.");
3692ffc8bcaSDan McDonald goto fail_tbolt_additional_buff;
3702ffc8bcaSDan McDonald }
3712ffc8bcaSDan McDonald
3722ffc8bcaSDan McDonald instance->ld_map_obj[i].status |= DMA_OBJ_ALLOCATED;
3732ffc8bcaSDan McDonald
3742ffc8bcaSDan McDonald bzero(instance->ld_map_obj[i].buffer, instance->size_map_info);
3752ffc8bcaSDan McDonald
3762ffc8bcaSDan McDonald instance->ld_map[i] =
3772ffc8bcaSDan McDonald (MR_FW_RAID_MAP_ALL *)instance->ld_map_obj[i].buffer;
3782ffc8bcaSDan McDonald instance->ld_map_phy[i] = (uint32_t)instance->
3792ffc8bcaSDan McDonald ld_map_obj[i].dma_cookie[0].dmac_address;
3802ffc8bcaSDan McDonald
3812ffc8bcaSDan McDonald con_log(CL_DLEVEL3, (CE_NOTE,
3822ffc8bcaSDan McDonald "ld_map Addr Phys 0x%x", instance->ld_map_phy[i]));
3832ffc8bcaSDan McDonald
3842ffc8bcaSDan McDonald con_log(CL_DLEVEL3, (CE_NOTE,
3852ffc8bcaSDan McDonald "size_map_info 0x%x", instance->size_map_info));
3862ffc8bcaSDan McDonald }
3872ffc8bcaSDan McDonald
3882ffc8bcaSDan McDonald return (DDI_SUCCESS);
3892ffc8bcaSDan McDonald
3902ffc8bcaSDan McDonald fail_tbolt_additional_buff:
3912ffc8bcaSDan McDonald mrsas_tbolt_free_additional_dma_buffer(instance);
3922ffc8bcaSDan McDonald
3932ffc8bcaSDan McDonald return (DDI_FAILURE);
3942ffc8bcaSDan McDonald }
3952ffc8bcaSDan McDonald
3962ffc8bcaSDan McDonald MRSAS_REQUEST_DESCRIPTOR_UNION *
mr_sas_get_request_descriptor(struct mrsas_instance * instance,uint16_t index)3972ffc8bcaSDan McDonald mr_sas_get_request_descriptor(struct mrsas_instance *instance, uint16_t index)
3982ffc8bcaSDan McDonald {
3992ffc8bcaSDan McDonald MRSAS_REQUEST_DESCRIPTOR_UNION *req_desc;
4002ffc8bcaSDan McDonald
4012ffc8bcaSDan McDonald if (index > instance->max_fw_cmds) {
4022ffc8bcaSDan McDonald con_log(CL_ANN1, (CE_NOTE,
4032ffc8bcaSDan McDonald "Invalid SMID 0x%x request for descriptor", index));
4042ffc8bcaSDan McDonald con_log(CL_ANN1, (CE_NOTE,
4052ffc8bcaSDan McDonald "max_fw_cmds : 0x%x", instance->max_fw_cmds));
4062ffc8bcaSDan McDonald return (NULL);
4072ffc8bcaSDan McDonald }
4082ffc8bcaSDan McDonald
4092ffc8bcaSDan McDonald req_desc = (MRSAS_REQUEST_DESCRIPTOR_UNION *)
4102ffc8bcaSDan McDonald ((char *)instance->request_message_pool +
4112ffc8bcaSDan McDonald (sizeof (MRSAS_REQUEST_DESCRIPTOR_UNION) * index));
4122ffc8bcaSDan McDonald
4132ffc8bcaSDan McDonald con_log(CL_ANN1, (CE_NOTE,
4142ffc8bcaSDan McDonald "request descriptor : 0x%08lx", (unsigned long)req_desc));
4152ffc8bcaSDan McDonald
4162ffc8bcaSDan McDonald con_log(CL_ANN1, (CE_NOTE,
4172ffc8bcaSDan McDonald "request descriptor base phy : 0x%08lx",
4182ffc8bcaSDan McDonald (unsigned long)instance->request_message_pool_phy));
4192ffc8bcaSDan McDonald
4202ffc8bcaSDan McDonald return ((MRSAS_REQUEST_DESCRIPTOR_UNION *)req_desc);
4212ffc8bcaSDan McDonald }
4222ffc8bcaSDan McDonald
4232ffc8bcaSDan McDonald
4242ffc8bcaSDan McDonald /*
4252ffc8bcaSDan McDonald * Allocate Request and Reply Queue Descriptors.
4262ffc8bcaSDan McDonald */
4272ffc8bcaSDan McDonald int
alloc_req_rep_desc(struct mrsas_instance * instance)4282ffc8bcaSDan McDonald alloc_req_rep_desc(struct mrsas_instance *instance)
4292ffc8bcaSDan McDonald {
4302ffc8bcaSDan McDonald uint32_t request_q_sz, reply_q_sz;
4312ffc8bcaSDan McDonald int i, max_reply_q_sz;
4322ffc8bcaSDan McDonald MPI2_REPLY_DESCRIPTORS_UNION *reply_desc;
4332ffc8bcaSDan McDonald
4342ffc8bcaSDan McDonald /*
4352ffc8bcaSDan McDonald * ThunderBolt(TB) There's no longer producer consumer mechanism.
4362ffc8bcaSDan McDonald * Once we have an interrupt we are supposed to scan through the list of
4372ffc8bcaSDan McDonald * reply descriptors and process them accordingly. We would be needing
4382ffc8bcaSDan McDonald * to allocate memory for 1024 reply descriptors
4392ffc8bcaSDan McDonald */
4402ffc8bcaSDan McDonald
4412ffc8bcaSDan McDonald /* Allocate Reply Descriptors */
4422ffc8bcaSDan McDonald con_log(CL_ANN1, (CE_NOTE, " reply q desc len = %x",
4432ffc8bcaSDan McDonald (uint_t)sizeof (MPI2_REPLY_DESCRIPTORS_UNION)));
4442ffc8bcaSDan McDonald
4452ffc8bcaSDan McDonald /* reply queue size should be multiple of 16 */
4462ffc8bcaSDan McDonald max_reply_q_sz = ((instance->max_fw_cmds + 1 + 15)/16)*16;
4472ffc8bcaSDan McDonald
4482ffc8bcaSDan McDonald reply_q_sz = 8 * max_reply_q_sz;
4492ffc8bcaSDan McDonald
4502ffc8bcaSDan McDonald
4512ffc8bcaSDan McDonald con_log(CL_ANN1, (CE_NOTE, " reply q desc len = %x",
4522ffc8bcaSDan McDonald (uint_t)sizeof (MPI2_REPLY_DESCRIPTORS_UNION)));
4532ffc8bcaSDan McDonald
4542ffc8bcaSDan McDonald instance->reply_desc_dma_obj.size = reply_q_sz;
4552ffc8bcaSDan McDonald instance->reply_desc_dma_obj.dma_attr = mrsas_generic_dma_attr;
4562ffc8bcaSDan McDonald instance->reply_desc_dma_obj.dma_attr.dma_attr_addr_hi = 0xFFFFFFFFU;
4572ffc8bcaSDan McDonald instance->reply_desc_dma_obj.dma_attr.dma_attr_count_max = 0xFFFFFFFFU;
4582ffc8bcaSDan McDonald instance->reply_desc_dma_obj.dma_attr.dma_attr_sgllen = 1;
4592ffc8bcaSDan McDonald instance->reply_desc_dma_obj.dma_attr.dma_attr_align = 16;
4602ffc8bcaSDan McDonald
4612ffc8bcaSDan McDonald if (mrsas_alloc_dma_obj(instance, &instance->reply_desc_dma_obj,
4622ffc8bcaSDan McDonald (uchar_t)DDI_STRUCTURE_LE_ACC) != 1) {
463ff38cf9dSAndy Fiddaman dev_err(instance->dip, CE_WARN, "could not alloc reply queue");
4642ffc8bcaSDan McDonald return (DDI_FAILURE);
4652ffc8bcaSDan McDonald }
4662ffc8bcaSDan McDonald
4672ffc8bcaSDan McDonald bzero(instance->reply_desc_dma_obj.buffer, reply_q_sz);
4682ffc8bcaSDan McDonald instance->reply_desc_dma_obj.status |= DMA_OBJ_ALLOCATED;
4692ffc8bcaSDan McDonald
4702ffc8bcaSDan McDonald /* virtual address of reply queue */
4712ffc8bcaSDan McDonald instance->reply_frame_pool = (MPI2_REPLY_DESCRIPTORS_UNION *)(
4722ffc8bcaSDan McDonald instance->reply_desc_dma_obj.buffer);
4732ffc8bcaSDan McDonald
4742ffc8bcaSDan McDonald instance->reply_q_depth = max_reply_q_sz;
4752ffc8bcaSDan McDonald
4762ffc8bcaSDan McDonald con_log(CL_ANN1, (CE_NOTE, "[reply queue depth]0x%x",
4772ffc8bcaSDan McDonald instance->reply_q_depth));
4782ffc8bcaSDan McDonald
4792ffc8bcaSDan McDonald con_log(CL_ANN1, (CE_NOTE, "[reply queue virt addr]0x%p",
4802ffc8bcaSDan McDonald (void *)instance->reply_frame_pool));
4812ffc8bcaSDan McDonald
4822ffc8bcaSDan McDonald /* initializing reply address to 0xFFFFFFFF */
4832ffc8bcaSDan McDonald reply_desc = instance->reply_frame_pool;
4842ffc8bcaSDan McDonald
4852ffc8bcaSDan McDonald for (i = 0; i < instance->reply_q_depth; i++) {
4862ffc8bcaSDan McDonald reply_desc->Words = (uint64_t)~0;
4872ffc8bcaSDan McDonald reply_desc++;
4882ffc8bcaSDan McDonald }
4892ffc8bcaSDan McDonald
4902ffc8bcaSDan McDonald
4912ffc8bcaSDan McDonald instance->reply_frame_pool_phy =
4922ffc8bcaSDan McDonald (uint32_t)instance->reply_desc_dma_obj.dma_cookie[0].dmac_address;
4932ffc8bcaSDan McDonald
4942ffc8bcaSDan McDonald con_log(CL_ANN1, (CE_NOTE,
4952ffc8bcaSDan McDonald "[reply queue phys addr]0x%x", instance->reply_frame_pool_phy));
4962ffc8bcaSDan McDonald
4972ffc8bcaSDan McDonald
4982ffc8bcaSDan McDonald instance->reply_pool_limit_phy = (instance->reply_frame_pool_phy +
4992ffc8bcaSDan McDonald reply_q_sz);
5002ffc8bcaSDan McDonald
5012ffc8bcaSDan McDonald con_log(CL_ANN1, (CE_NOTE, "[reply pool limit phys addr]0x%x",
5022ffc8bcaSDan McDonald instance->reply_pool_limit_phy));
5032ffc8bcaSDan McDonald
5042ffc8bcaSDan McDonald
5052ffc8bcaSDan McDonald con_log(CL_ANN1, (CE_NOTE, " request q desc len = %x",
5062ffc8bcaSDan McDonald (int)sizeof (MRSAS_REQUEST_DESCRIPTOR_UNION)));
5072ffc8bcaSDan McDonald
5082ffc8bcaSDan McDonald /* Allocate Request Descriptors */
5092ffc8bcaSDan McDonald con_log(CL_ANN1, (CE_NOTE, " request q desc len = %x",
5102ffc8bcaSDan McDonald (int)sizeof (MRSAS_REQUEST_DESCRIPTOR_UNION)));
5112ffc8bcaSDan McDonald
5122ffc8bcaSDan McDonald request_q_sz = 8 *
5132ffc8bcaSDan McDonald (instance->max_fw_cmds);
5142ffc8bcaSDan McDonald
5152ffc8bcaSDan McDonald instance->request_desc_dma_obj.size = request_q_sz;
5162ffc8bcaSDan McDonald instance->request_desc_dma_obj.dma_attr = mrsas_generic_dma_attr;
5172ffc8bcaSDan McDonald instance->request_desc_dma_obj.dma_attr.dma_attr_addr_hi = 0xFFFFFFFFU;
5182ffc8bcaSDan McDonald instance->request_desc_dma_obj.dma_attr.dma_attr_count_max =
5192ffc8bcaSDan McDonald 0xFFFFFFFFU;
5202ffc8bcaSDan McDonald instance->request_desc_dma_obj.dma_attr.dma_attr_sgllen = 1;
5212ffc8bcaSDan McDonald instance->request_desc_dma_obj.dma_attr.dma_attr_align = 16;
5222ffc8bcaSDan McDonald
5232ffc8bcaSDan McDonald if (mrsas_alloc_dma_obj(instance, &instance->request_desc_dma_obj,
5242ffc8bcaSDan McDonald (uchar_t)DDI_STRUCTURE_LE_ACC) != 1) {
525ff38cf9dSAndy Fiddaman dev_err(instance->dip, CE_WARN,
526ff38cf9dSAndy Fiddaman "could not alloc request queue desc");
5272ffc8bcaSDan McDonald goto fail_undo_reply_queue;
5282ffc8bcaSDan McDonald }
5292ffc8bcaSDan McDonald
5302ffc8bcaSDan McDonald bzero(instance->request_desc_dma_obj.buffer, request_q_sz);
5312ffc8bcaSDan McDonald instance->request_desc_dma_obj.status |= DMA_OBJ_ALLOCATED;
5322ffc8bcaSDan McDonald
5332ffc8bcaSDan McDonald /* virtual address of request queue desc */
5342ffc8bcaSDan McDonald instance->request_message_pool = (MRSAS_REQUEST_DESCRIPTOR_UNION *)
5352ffc8bcaSDan McDonald (instance->request_desc_dma_obj.buffer);
5362ffc8bcaSDan McDonald
5372ffc8bcaSDan McDonald instance->request_message_pool_phy =
5382ffc8bcaSDan McDonald (uint32_t)instance->request_desc_dma_obj.dma_cookie[0].dmac_address;
5392ffc8bcaSDan McDonald
5402ffc8bcaSDan McDonald return (DDI_SUCCESS);
5412ffc8bcaSDan McDonald
5422ffc8bcaSDan McDonald fail_undo_reply_queue:
5432ffc8bcaSDan McDonald if (instance->reply_desc_dma_obj.status == DMA_OBJ_ALLOCATED) {
5442ffc8bcaSDan McDonald (void) mrsas_free_dma_obj(instance,
5452ffc8bcaSDan McDonald instance->reply_desc_dma_obj);
5462ffc8bcaSDan McDonald instance->reply_desc_dma_obj.status = DMA_OBJ_FREED;
5472ffc8bcaSDan McDonald }
5482ffc8bcaSDan McDonald
5492ffc8bcaSDan McDonald return (DDI_FAILURE);
5502ffc8bcaSDan McDonald }
5512ffc8bcaSDan McDonald
5522ffc8bcaSDan McDonald /*
5532ffc8bcaSDan McDonald * mrsas_alloc_cmd_pool_tbolt
5542ffc8bcaSDan McDonald *
5552ffc8bcaSDan McDonald * TODO: merge tbolt-specific code into mrsas_alloc_cmd_pool() to have single
5562ffc8bcaSDan McDonald * routine
5572ffc8bcaSDan McDonald */
5582ffc8bcaSDan McDonald int
mrsas_alloc_cmd_pool_tbolt(struct mrsas_instance * instance)5592ffc8bcaSDan McDonald mrsas_alloc_cmd_pool_tbolt(struct mrsas_instance *instance)
5602ffc8bcaSDan McDonald {
5612ffc8bcaSDan McDonald int i;
5622ffc8bcaSDan McDonald int count;
5632ffc8bcaSDan McDonald uint32_t max_cmd;
5642ffc8bcaSDan McDonald uint32_t reserve_cmd;
5652ffc8bcaSDan McDonald size_t sz;
5662ffc8bcaSDan McDonald
5672ffc8bcaSDan McDonald struct mrsas_cmd *cmd;
5682ffc8bcaSDan McDonald
5692ffc8bcaSDan McDonald max_cmd = instance->max_fw_cmds;
5702ffc8bcaSDan McDonald con_log(CL_ANN1, (CE_NOTE, "mrsas_alloc_cmd_pool: "
5712ffc8bcaSDan McDonald "max_cmd %x", max_cmd));
5722ffc8bcaSDan McDonald
5732ffc8bcaSDan McDonald
5742ffc8bcaSDan McDonald sz = sizeof (struct mrsas_cmd *) * max_cmd;
5752ffc8bcaSDan McDonald
5762ffc8bcaSDan McDonald /*
5772ffc8bcaSDan McDonald * instance->cmd_list is an array of struct mrsas_cmd pointers.
5782ffc8bcaSDan McDonald * Allocate the dynamic array first and then allocate individual
5792ffc8bcaSDan McDonald * commands.
5802ffc8bcaSDan McDonald */
5812ffc8bcaSDan McDonald instance->cmd_list = kmem_zalloc(sz, KM_SLEEP);
5822ffc8bcaSDan McDonald
5832ffc8bcaSDan McDonald /* create a frame pool and assign one frame to each cmd */
5842ffc8bcaSDan McDonald for (count = 0; count < max_cmd; count++) {
5852ffc8bcaSDan McDonald instance->cmd_list[count] =
5862ffc8bcaSDan McDonald kmem_zalloc(sizeof (struct mrsas_cmd), KM_SLEEP);
5872ffc8bcaSDan McDonald }
5882ffc8bcaSDan McDonald
5892ffc8bcaSDan McDonald /* add all the commands to command pool */
5902ffc8bcaSDan McDonald
5912ffc8bcaSDan McDonald INIT_LIST_HEAD(&instance->cmd_pool_list);
5922ffc8bcaSDan McDonald INIT_LIST_HEAD(&instance->cmd_pend_list);
5932ffc8bcaSDan McDonald INIT_LIST_HEAD(&instance->cmd_app_pool_list);
5942ffc8bcaSDan McDonald
5952ffc8bcaSDan McDonald reserve_cmd = MRSAS_APP_RESERVED_CMDS;
5962ffc8bcaSDan McDonald
5972ffc8bcaSDan McDonald /* cmd index 0 reservered for IOC INIT */
5982ffc8bcaSDan McDonald for (i = 1; i < reserve_cmd; i++) {
5992ffc8bcaSDan McDonald cmd = instance->cmd_list[i];
6002ffc8bcaSDan McDonald cmd->index = i;
6012ffc8bcaSDan McDonald mlist_add_tail(&cmd->list, &instance->cmd_app_pool_list);
6022ffc8bcaSDan McDonald }
6032ffc8bcaSDan McDonald
6042ffc8bcaSDan McDonald
6052ffc8bcaSDan McDonald for (i = reserve_cmd; i < max_cmd; i++) {
6062ffc8bcaSDan McDonald cmd = instance->cmd_list[i];
6072ffc8bcaSDan McDonald cmd->index = i;
6082ffc8bcaSDan McDonald mlist_add_tail(&cmd->list, &instance->cmd_pool_list);
6092ffc8bcaSDan McDonald }
6102ffc8bcaSDan McDonald
6112ffc8bcaSDan McDonald return (DDI_SUCCESS);
6122ffc8bcaSDan McDonald
6132ffc8bcaSDan McDonald mrsas_undo_cmds:
6142ffc8bcaSDan McDonald if (count > 0) {
6152ffc8bcaSDan McDonald /* free each cmd */
6162ffc8bcaSDan McDonald for (i = 0; i < count; i++) {
6172ffc8bcaSDan McDonald if (instance->cmd_list[i] != NULL) {
6182ffc8bcaSDan McDonald kmem_free(instance->cmd_list[i],
6192ffc8bcaSDan McDonald sizeof (struct mrsas_cmd));
6202ffc8bcaSDan McDonald }
6212ffc8bcaSDan McDonald instance->cmd_list[i] = NULL;
6222ffc8bcaSDan McDonald }
6232ffc8bcaSDan McDonald }
6242ffc8bcaSDan McDonald
6252ffc8bcaSDan McDonald mrsas_undo_cmd_list:
6262ffc8bcaSDan McDonald if (instance->cmd_list != NULL)
6272ffc8bcaSDan McDonald kmem_free(instance->cmd_list, sz);
6282ffc8bcaSDan McDonald instance->cmd_list = NULL;
6292ffc8bcaSDan McDonald
6302ffc8bcaSDan McDonald return (DDI_FAILURE);
6312ffc8bcaSDan McDonald }
6322ffc8bcaSDan McDonald
6332ffc8bcaSDan McDonald
6342ffc8bcaSDan McDonald /*
6352ffc8bcaSDan McDonald * free_space_for_mpi2
6362ffc8bcaSDan McDonald */
6372ffc8bcaSDan McDonald void
free_space_for_mpi2(struct mrsas_instance * instance)6382ffc8bcaSDan McDonald free_space_for_mpi2(struct mrsas_instance *instance)
6392ffc8bcaSDan McDonald {
6402ffc8bcaSDan McDonald /* already freed */
6412ffc8bcaSDan McDonald if (instance->cmd_list == NULL) {
6422ffc8bcaSDan McDonald return;
6432ffc8bcaSDan McDonald }
6442ffc8bcaSDan McDonald
6452ffc8bcaSDan McDonald /* First free the additional DMA buffer */
6462ffc8bcaSDan McDonald mrsas_tbolt_free_additional_dma_buffer(instance);
6472ffc8bcaSDan McDonald
6482ffc8bcaSDan McDonald /* Free the request/reply descriptor pool */
6492ffc8bcaSDan McDonald free_req_rep_desc_pool(instance);
6502ffc8bcaSDan McDonald
6512ffc8bcaSDan McDonald /* Free the MPI message pool */
6522ffc8bcaSDan McDonald destroy_mpi2_frame_pool(instance);
6532ffc8bcaSDan McDonald
6542ffc8bcaSDan McDonald /* Free the MFI frame pool */
6552ffc8bcaSDan McDonald destroy_mfi_frame_pool(instance);
6562ffc8bcaSDan McDonald
6572ffc8bcaSDan McDonald /* Free all the commands in the cmd_list */
6582ffc8bcaSDan McDonald /* Free the cmd_list buffer itself */
6592ffc8bcaSDan McDonald mrsas_free_cmd_pool(instance);
6602ffc8bcaSDan McDonald }
6612ffc8bcaSDan McDonald
6622ffc8bcaSDan McDonald
6632ffc8bcaSDan McDonald /*
6642ffc8bcaSDan McDonald * ThunderBolt(TB) memory allocations for commands/messages/frames.
6652ffc8bcaSDan McDonald */
6662ffc8bcaSDan McDonald int
alloc_space_for_mpi2(struct mrsas_instance * instance)6672ffc8bcaSDan McDonald alloc_space_for_mpi2(struct mrsas_instance *instance)
6682ffc8bcaSDan McDonald {
6692ffc8bcaSDan McDonald /* Allocate command pool (memory for cmd_list & individual commands) */
6702ffc8bcaSDan McDonald if (mrsas_alloc_cmd_pool_tbolt(instance)) {
671ff38cf9dSAndy Fiddaman dev_err(instance->dip, CE_WARN, "Error creating cmd pool");
6722ffc8bcaSDan McDonald return (DDI_FAILURE);
6732ffc8bcaSDan McDonald }
6742ffc8bcaSDan McDonald
6752ffc8bcaSDan McDonald /* Initialize single reply size and Message size */
6762ffc8bcaSDan McDonald instance->reply_size = MRSAS_THUNDERBOLT_REPLY_SIZE;
6772ffc8bcaSDan McDonald instance->raid_io_msg_size = MRSAS_THUNDERBOLT_MSG_SIZE;
6782ffc8bcaSDan McDonald
6792ffc8bcaSDan McDonald instance->max_sge_in_main_msg = (MRSAS_THUNDERBOLT_MSG_SIZE -
6802ffc8bcaSDan McDonald (sizeof (MPI2_RAID_SCSI_IO_REQUEST) -
6812ffc8bcaSDan McDonald sizeof (MPI2_SGE_IO_UNION)))/ sizeof (MPI2_SGE_IO_UNION);
6822ffc8bcaSDan McDonald instance->max_sge_in_chain = (MR_COMMAND_SIZE -
6832ffc8bcaSDan McDonald MRSAS_THUNDERBOLT_MSG_SIZE) / sizeof (MPI2_SGE_IO_UNION);
6842ffc8bcaSDan McDonald
6852ffc8bcaSDan McDonald /* Reduce SG count by 1 to take care of group cmds feature in FW */
6862ffc8bcaSDan McDonald instance->max_num_sge = (instance->max_sge_in_main_msg +
6872ffc8bcaSDan McDonald instance->max_sge_in_chain - 2);
6882ffc8bcaSDan McDonald instance->chain_offset_mpt_msg =
6892ffc8bcaSDan McDonald offsetof(MPI2_RAID_SCSI_IO_REQUEST, SGL) / 16;
6902ffc8bcaSDan McDonald instance->chain_offset_io_req = (MRSAS_THUNDERBOLT_MSG_SIZE -
6912ffc8bcaSDan McDonald sizeof (MPI2_SGE_IO_UNION)) / 16;
6922ffc8bcaSDan McDonald instance->reply_read_index = 0;
6932ffc8bcaSDan McDonald
6942ffc8bcaSDan McDonald
6952ffc8bcaSDan McDonald /* Allocate Request and Reply descriptors Array */
6962ffc8bcaSDan McDonald /* Make sure the buffer is aligned to 8 for req/rep descriptor Pool */
6972ffc8bcaSDan McDonald if (alloc_req_rep_desc(instance)) {
698ff38cf9dSAndy Fiddaman dev_err(instance->dip, CE_WARN,
6992ffc8bcaSDan McDonald "Error, allocating memory for descripter-pool");
7002ffc8bcaSDan McDonald goto mpi2_undo_cmd_pool;
7012ffc8bcaSDan McDonald }
7022ffc8bcaSDan McDonald con_log(CL_ANN1, (CE_NOTE, "[request message pool phys addr]0x%x",
7032ffc8bcaSDan McDonald instance->request_message_pool_phy));
7042ffc8bcaSDan McDonald
7052ffc8bcaSDan McDonald
7062ffc8bcaSDan McDonald /* Allocate MFI Frame pool - for MPI-MFI passthru commands */
7072ffc8bcaSDan McDonald if (create_mfi_frame_pool(instance)) {
708ff38cf9dSAndy Fiddaman dev_err(instance->dip, CE_WARN,
7092ffc8bcaSDan McDonald "Error, allocating memory for MFI frame-pool");
7102ffc8bcaSDan McDonald goto mpi2_undo_descripter_pool;
7112ffc8bcaSDan McDonald }
7122ffc8bcaSDan McDonald
7132ffc8bcaSDan McDonald
7142ffc8bcaSDan McDonald /* Allocate MPI2 Message pool */
7152ffc8bcaSDan McDonald /*
7162ffc8bcaSDan McDonald * Make sure the buffer is alligned to 256 for raid message packet
7172ffc8bcaSDan McDonald * create a io request pool and assign one frame to each cmd
7182ffc8bcaSDan McDonald */
7192ffc8bcaSDan McDonald
7202ffc8bcaSDan McDonald if (create_mpi2_frame_pool(instance)) {
721ff38cf9dSAndy Fiddaman dev_err(instance->dip, CE_WARN,
7222ffc8bcaSDan McDonald "Error, allocating memory for MPI2 Message-pool");
7232ffc8bcaSDan McDonald goto mpi2_undo_mfi_frame_pool;
7242ffc8bcaSDan McDonald }
7252ffc8bcaSDan McDonald
7262ffc8bcaSDan McDonald #ifdef DEBUG
7272ffc8bcaSDan McDonald con_log(CL_ANN1, (CE_CONT, "[max_sge_in_main_msg]0x%x",
7282ffc8bcaSDan McDonald instance->max_sge_in_main_msg));
7292ffc8bcaSDan McDonald con_log(CL_ANN1, (CE_CONT, "[max_sge_in_chain]0x%x",
7302ffc8bcaSDan McDonald instance->max_sge_in_chain));
7312ffc8bcaSDan McDonald con_log(CL_ANN1, (CE_CONT,
7322ffc8bcaSDan McDonald "[max_sge]0x%x", instance->max_num_sge));
7332ffc8bcaSDan McDonald con_log(CL_ANN1, (CE_CONT, "[chain_offset_mpt_msg]0x%x",
7342ffc8bcaSDan McDonald instance->chain_offset_mpt_msg));
7352ffc8bcaSDan McDonald con_log(CL_ANN1, (CE_CONT, "[chain_offset_io_req]0x%x",
7362ffc8bcaSDan McDonald instance->chain_offset_io_req));
7372ffc8bcaSDan McDonald #endif
7382ffc8bcaSDan McDonald
7392ffc8bcaSDan McDonald
7402ffc8bcaSDan McDonald /* Allocate additional dma buffer */
7412ffc8bcaSDan McDonald if (mrsas_tbolt_alloc_additional_dma_buffer(instance)) {
742ff38cf9dSAndy Fiddaman dev_err(instance->dip, CE_WARN,
7432ffc8bcaSDan McDonald "Error, allocating tbolt additional DMA buffer");
7442ffc8bcaSDan McDonald goto mpi2_undo_message_pool;
7452ffc8bcaSDan McDonald }
7462ffc8bcaSDan McDonald
7472ffc8bcaSDan McDonald return (DDI_SUCCESS);
7482ffc8bcaSDan McDonald
7492ffc8bcaSDan McDonald mpi2_undo_message_pool:
7502ffc8bcaSDan McDonald destroy_mpi2_frame_pool(instance);
7512ffc8bcaSDan McDonald
7522ffc8bcaSDan McDonald mpi2_undo_mfi_frame_pool:
7532ffc8bcaSDan McDonald destroy_mfi_frame_pool(instance);
7542ffc8bcaSDan McDonald
7552ffc8bcaSDan McDonald mpi2_undo_descripter_pool:
7562ffc8bcaSDan McDonald free_req_rep_desc_pool(instance);
7572ffc8bcaSDan McDonald
7582ffc8bcaSDan McDonald mpi2_undo_cmd_pool:
7592ffc8bcaSDan McDonald mrsas_free_cmd_pool(instance);
7602ffc8bcaSDan McDonald
7612ffc8bcaSDan McDonald return (DDI_FAILURE);
7622ffc8bcaSDan McDonald }
7632ffc8bcaSDan McDonald
7642ffc8bcaSDan McDonald
7652ffc8bcaSDan McDonald /*
7662ffc8bcaSDan McDonald * mrsas_init_adapter_tbolt - Initialize fusion interface adapter.
7672ffc8bcaSDan McDonald */
7682ffc8bcaSDan McDonald int
mrsas_init_adapter_tbolt(struct mrsas_instance * instance)7692ffc8bcaSDan McDonald mrsas_init_adapter_tbolt(struct mrsas_instance *instance)
7702ffc8bcaSDan McDonald {
7712ffc8bcaSDan McDonald
7722ffc8bcaSDan McDonald /*
7732ffc8bcaSDan McDonald * Reduce the max supported cmds by 1. This is to ensure that the
7742ffc8bcaSDan McDonald * reply_q_sz (1 more than the max cmd that driver may send)
7752ffc8bcaSDan McDonald * does not exceed max cmds that the FW can support
7762ffc8bcaSDan McDonald */
7772ffc8bcaSDan McDonald
7782ffc8bcaSDan McDonald if (instance->max_fw_cmds > 1008) {
7792ffc8bcaSDan McDonald instance->max_fw_cmds = 1008;
7802ffc8bcaSDan McDonald instance->max_fw_cmds = instance->max_fw_cmds-1;
7812ffc8bcaSDan McDonald }
7822ffc8bcaSDan McDonald
7832ffc8bcaSDan McDonald con_log(CL_ANN, (CE_NOTE, "mrsas_init_adapter_tbolt: "
7842ffc8bcaSDan McDonald "instance->max_fw_cmds 0x%X.", instance->max_fw_cmds));
7852ffc8bcaSDan McDonald
7862ffc8bcaSDan McDonald
7872ffc8bcaSDan McDonald /* create a pool of commands */
7882ffc8bcaSDan McDonald if (alloc_space_for_mpi2(instance) != DDI_SUCCESS) {
789ff38cf9dSAndy Fiddaman dev_err(instance->dip, CE_WARN,
7902ffc8bcaSDan McDonald "alloc_space_for_mpi2() failed.");
7912ffc8bcaSDan McDonald
7922ffc8bcaSDan McDonald return (DDI_FAILURE);
7932ffc8bcaSDan McDonald }
7942ffc8bcaSDan McDonald
7952ffc8bcaSDan McDonald /* Send ioc init message */
7962ffc8bcaSDan McDonald /* NOTE: the issue_init call does FMA checking already. */
7972ffc8bcaSDan McDonald if (mrsas_issue_init_mpi2(instance) != DDI_SUCCESS) {
798ff38cf9dSAndy Fiddaman dev_err(instance->dip, CE_WARN,
7992ffc8bcaSDan McDonald "mrsas_issue_init_mpi2() failed.");
8002ffc8bcaSDan McDonald
8012ffc8bcaSDan McDonald goto fail_init_fusion;
8022ffc8bcaSDan McDonald }
8032ffc8bcaSDan McDonald
8042ffc8bcaSDan McDonald instance->unroll.alloc_space_mpi2 = 1;
8052ffc8bcaSDan McDonald
8062ffc8bcaSDan McDonald con_log(CL_ANN, (CE_NOTE,
8072ffc8bcaSDan McDonald "mrsas_init_adapter_tbolt: SUCCESSFUL"));
8082ffc8bcaSDan McDonald
8092ffc8bcaSDan McDonald return (DDI_SUCCESS);
8102ffc8bcaSDan McDonald
8112ffc8bcaSDan McDonald fail_init_fusion:
8122ffc8bcaSDan McDonald free_space_for_mpi2(instance);
8132ffc8bcaSDan McDonald
8142ffc8bcaSDan McDonald return (DDI_FAILURE);
8152ffc8bcaSDan McDonald }
8162ffc8bcaSDan McDonald
8172ffc8bcaSDan McDonald
8182ffc8bcaSDan McDonald
8192ffc8bcaSDan McDonald /*
8202ffc8bcaSDan McDonald * init_mpi2
8212ffc8bcaSDan McDonald */
8222ffc8bcaSDan McDonald int
mrsas_issue_init_mpi2(struct mrsas_instance * instance)8232ffc8bcaSDan McDonald mrsas_issue_init_mpi2(struct mrsas_instance *instance)
8242ffc8bcaSDan McDonald {
8252ffc8bcaSDan McDonald dma_obj_t init2_dma_obj;
8262ffc8bcaSDan McDonald int ret_val = DDI_SUCCESS;
8272ffc8bcaSDan McDonald
8282ffc8bcaSDan McDonald /* allocate DMA buffer for IOC INIT message */
8292ffc8bcaSDan McDonald init2_dma_obj.size = sizeof (Mpi2IOCInitRequest_t);
8302ffc8bcaSDan McDonald init2_dma_obj.dma_attr = mrsas_generic_dma_attr;
8312ffc8bcaSDan McDonald init2_dma_obj.dma_attr.dma_attr_addr_hi = 0xFFFFFFFFU;
8322ffc8bcaSDan McDonald init2_dma_obj.dma_attr.dma_attr_count_max = 0xFFFFFFFFU;
8332ffc8bcaSDan McDonald init2_dma_obj.dma_attr.dma_attr_sgllen = 1;
8342ffc8bcaSDan McDonald init2_dma_obj.dma_attr.dma_attr_align = 256;
8352ffc8bcaSDan McDonald
8362ffc8bcaSDan McDonald if (mrsas_alloc_dma_obj(instance, &init2_dma_obj,
8372ffc8bcaSDan McDonald (uchar_t)DDI_STRUCTURE_LE_ACC) != 1) {
838ff38cf9dSAndy Fiddaman dev_err(instance->dip, CE_WARN, "mr_sas_issue_init_mpi2 "
8392ffc8bcaSDan McDonald "could not allocate data transfer buffer.");
8402ffc8bcaSDan McDonald return (DDI_FAILURE);
8412ffc8bcaSDan McDonald }
8422ffc8bcaSDan McDonald (void) memset(init2_dma_obj.buffer, 2, sizeof (Mpi2IOCInitRequest_t));
8432ffc8bcaSDan McDonald
8442ffc8bcaSDan McDonald con_log(CL_ANN1, (CE_NOTE,
8452ffc8bcaSDan McDonald "mrsas_issue_init_mpi2 _phys adr: %x",
8462ffc8bcaSDan McDonald init2_dma_obj.dma_cookie[0].dmac_address));
8472ffc8bcaSDan McDonald
8482ffc8bcaSDan McDonald
8492ffc8bcaSDan McDonald /* Initialize and send ioc init message */
8502ffc8bcaSDan McDonald ret_val = mrsas_tbolt_ioc_init(instance, &init2_dma_obj);
8512ffc8bcaSDan McDonald if (ret_val == DDI_FAILURE) {
8522ffc8bcaSDan McDonald con_log(CL_ANN1, (CE_WARN,
8532ffc8bcaSDan McDonald "mrsas_issue_init_mpi2: Failed"));
8542ffc8bcaSDan McDonald goto fail_init_mpi2;
8552ffc8bcaSDan McDonald }
8562ffc8bcaSDan McDonald
8572ffc8bcaSDan McDonald /* free IOC init DMA buffer */
8582ffc8bcaSDan McDonald if (mrsas_free_dma_obj(instance, init2_dma_obj)
8592ffc8bcaSDan McDonald != DDI_SUCCESS) {
8602ffc8bcaSDan McDonald con_log(CL_ANN1, (CE_WARN,
8612ffc8bcaSDan McDonald "mrsas_issue_init_mpi2: Free Failed"));
8622ffc8bcaSDan McDonald return (DDI_FAILURE);
8632ffc8bcaSDan McDonald }
8642ffc8bcaSDan McDonald
8652ffc8bcaSDan McDonald /* Get/Check and sync ld_map info */
8662ffc8bcaSDan McDonald instance->map_id = 0;
8672ffc8bcaSDan McDonald if (mrsas_tbolt_check_map_info(instance) == DDI_SUCCESS)
8682ffc8bcaSDan McDonald (void) mrsas_tbolt_sync_map_info(instance);
8692ffc8bcaSDan McDonald
8702ffc8bcaSDan McDonald
8712ffc8bcaSDan McDonald /* No mrsas_cmd to send, so send NULL. */
8722ffc8bcaSDan McDonald if (mrsas_common_check(instance, NULL) != DDI_SUCCESS)
8732ffc8bcaSDan McDonald goto fail_init_mpi2;
8742ffc8bcaSDan McDonald
8752ffc8bcaSDan McDonald con_log(CL_ANN, (CE_NOTE,
8762ffc8bcaSDan McDonald "mrsas_issue_init_mpi2: SUCCESSFUL"));
8772ffc8bcaSDan McDonald
8782ffc8bcaSDan McDonald return (DDI_SUCCESS);
8792ffc8bcaSDan McDonald
8802ffc8bcaSDan McDonald fail_init_mpi2:
8812ffc8bcaSDan McDonald (void) mrsas_free_dma_obj(instance, init2_dma_obj);
8822ffc8bcaSDan McDonald
8832ffc8bcaSDan McDonald return (DDI_FAILURE);
8842ffc8bcaSDan McDonald }
8852ffc8bcaSDan McDonald
8862ffc8bcaSDan McDonald static int
mrsas_tbolt_ioc_init(struct mrsas_instance * instance,dma_obj_t * mpi2_dma_obj)8872ffc8bcaSDan McDonald mrsas_tbolt_ioc_init(struct mrsas_instance *instance, dma_obj_t *mpi2_dma_obj)
8882ffc8bcaSDan McDonald {
8892ffc8bcaSDan McDonald int numbytes;
8902ffc8bcaSDan McDonald uint16_t flags;
8912ffc8bcaSDan McDonald struct mrsas_init_frame2 *mfiFrameInit2;
8922ffc8bcaSDan McDonald struct mrsas_header *frame_hdr;
8932ffc8bcaSDan McDonald Mpi2IOCInitRequest_t *init;
8942ffc8bcaSDan McDonald struct mrsas_cmd *cmd = NULL;
8952ffc8bcaSDan McDonald struct mrsas_drv_ver drv_ver_info;
8964bc492d2SAndy Fiddaman MRSAS_REQUEST_DESCRIPTOR_UNION req_desc;
8974bc492d2SAndy Fiddaman uint32_t timeout;
8982ffc8bcaSDan McDonald
8992ffc8bcaSDan McDonald con_log(CL_ANN, (CE_NOTE, "chkpnt:%s:%d", __func__, __LINE__));
9002ffc8bcaSDan McDonald
9012ffc8bcaSDan McDonald
9022ffc8bcaSDan McDonald #ifdef DEBUG
9032ffc8bcaSDan McDonald con_log(CL_ANN1, (CE_CONT, " mfiFrameInit2 len = %x\n",
9042ffc8bcaSDan McDonald (int)sizeof (*mfiFrameInit2)));
9052ffc8bcaSDan McDonald con_log(CL_ANN1, (CE_CONT, " MPI len = %x\n", (int)sizeof (*init)));
9062ffc8bcaSDan McDonald con_log(CL_ANN1, (CE_CONT, " mfiFrameInit2 len = %x\n",
9072ffc8bcaSDan McDonald (int)sizeof (struct mrsas_init_frame2)));
9082ffc8bcaSDan McDonald con_log(CL_ANN1, (CE_CONT, " MPI len = %x\n",
9092ffc8bcaSDan McDonald (int)sizeof (Mpi2IOCInitRequest_t)));
9102ffc8bcaSDan McDonald #endif
9112ffc8bcaSDan McDonald
9122ffc8bcaSDan McDonald init = (Mpi2IOCInitRequest_t *)mpi2_dma_obj->buffer;
9132ffc8bcaSDan McDonald numbytes = sizeof (*init);
9142ffc8bcaSDan McDonald bzero(init, numbytes);
9152ffc8bcaSDan McDonald
9162ffc8bcaSDan McDonald ddi_put8(mpi2_dma_obj->acc_handle, &init->Function,
9172ffc8bcaSDan McDonald MPI2_FUNCTION_IOC_INIT);
9182ffc8bcaSDan McDonald
9192ffc8bcaSDan McDonald ddi_put8(mpi2_dma_obj->acc_handle, &init->WhoInit,
9202ffc8bcaSDan McDonald MPI2_WHOINIT_HOST_DRIVER);
9212ffc8bcaSDan McDonald
9222ffc8bcaSDan McDonald /* set MsgVersion and HeaderVersion host driver was built with */
9232ffc8bcaSDan McDonald ddi_put16(mpi2_dma_obj->acc_handle, &init->MsgVersion,
9242ffc8bcaSDan McDonald MPI2_VERSION);
9252ffc8bcaSDan McDonald
9262ffc8bcaSDan McDonald ddi_put16(mpi2_dma_obj->acc_handle, &init->HeaderVersion,
9272ffc8bcaSDan McDonald MPI2_HEADER_VERSION);
9282ffc8bcaSDan McDonald
9292ffc8bcaSDan McDonald ddi_put16(mpi2_dma_obj->acc_handle, &init->SystemRequestFrameSize,
9302ffc8bcaSDan McDonald instance->raid_io_msg_size / 4);
9312ffc8bcaSDan McDonald
9322ffc8bcaSDan McDonald ddi_put16(mpi2_dma_obj->acc_handle, &init->ReplyFreeQueueDepth,
9332ffc8bcaSDan McDonald 0);
9342ffc8bcaSDan McDonald
9352ffc8bcaSDan McDonald ddi_put16(mpi2_dma_obj->acc_handle,
9362ffc8bcaSDan McDonald &init->ReplyDescriptorPostQueueDepth,
9372ffc8bcaSDan McDonald instance->reply_q_depth);
9382ffc8bcaSDan McDonald /*
9392ffc8bcaSDan McDonald * These addresses are set using the DMA cookie addresses from when the
9402ffc8bcaSDan McDonald * memory was allocated. Sense buffer hi address should be 0.
9412ffc8bcaSDan McDonald * ddi_put32(accessp, &init->SenseBufferAddressHigh, 0);
9422ffc8bcaSDan McDonald */
9432ffc8bcaSDan McDonald
9442ffc8bcaSDan McDonald ddi_put32(mpi2_dma_obj->acc_handle,
9452ffc8bcaSDan McDonald &init->SenseBufferAddressHigh, 0);
9462ffc8bcaSDan McDonald
9472ffc8bcaSDan McDonald ddi_put64(mpi2_dma_obj->acc_handle,
9482ffc8bcaSDan McDonald (uint64_t *)&init->SystemRequestFrameBaseAddress,
9492ffc8bcaSDan McDonald instance->io_request_frames_phy);
9502ffc8bcaSDan McDonald
9512ffc8bcaSDan McDonald ddi_put64(mpi2_dma_obj->acc_handle,
9522ffc8bcaSDan McDonald &init->ReplyDescriptorPostQueueAddress,
9532ffc8bcaSDan McDonald instance->reply_frame_pool_phy);
9542ffc8bcaSDan McDonald
9552ffc8bcaSDan McDonald ddi_put64(mpi2_dma_obj->acc_handle,
9562ffc8bcaSDan McDonald &init->ReplyFreeQueueAddress, 0);
9572ffc8bcaSDan McDonald
9582ffc8bcaSDan McDonald cmd = instance->cmd_list[0];
9592ffc8bcaSDan McDonald if (cmd == NULL) {
9602ffc8bcaSDan McDonald return (DDI_FAILURE);
9612ffc8bcaSDan McDonald }
9622ffc8bcaSDan McDonald cmd->retry_count_for_ocr = 0;
9632ffc8bcaSDan McDonald cmd->pkt = NULL;
9642ffc8bcaSDan McDonald cmd->drv_pkt_time = 0;
9652ffc8bcaSDan McDonald
9662ffc8bcaSDan McDonald mfiFrameInit2 = (struct mrsas_init_frame2 *)cmd->scsi_io_request;
9672ffc8bcaSDan McDonald con_log(CL_ANN1, (CE_CONT, "[mfi vaddr]%p", (void *)mfiFrameInit2));
9682ffc8bcaSDan McDonald
9692ffc8bcaSDan McDonald frame_hdr = &cmd->frame->hdr;
9702ffc8bcaSDan McDonald
9712ffc8bcaSDan McDonald ddi_put8(cmd->frame_dma_obj.acc_handle, &frame_hdr->cmd_status,
9722ffc8bcaSDan McDonald MFI_CMD_STATUS_POLL_MODE);
9732ffc8bcaSDan McDonald
9742ffc8bcaSDan McDonald flags = ddi_get16(cmd->frame_dma_obj.acc_handle, &frame_hdr->flags);
9752ffc8bcaSDan McDonald
9762ffc8bcaSDan McDonald flags |= MFI_FRAME_DONT_POST_IN_REPLY_QUEUE;
9772ffc8bcaSDan McDonald
9782ffc8bcaSDan McDonald ddi_put16(cmd->frame_dma_obj.acc_handle, &frame_hdr->flags, flags);
9792ffc8bcaSDan McDonald
9802ffc8bcaSDan McDonald con_log(CL_ANN, (CE_CONT,
9812ffc8bcaSDan McDonald "mrsas_tbolt_ioc_init: SMID:%x\n", cmd->SMID));
9822ffc8bcaSDan McDonald
9832ffc8bcaSDan McDonald /* Init the MFI Header */
9842ffc8bcaSDan McDonald ddi_put8(instance->mpi2_frame_pool_dma_obj.acc_handle,
9852ffc8bcaSDan McDonald &mfiFrameInit2->cmd, MFI_CMD_OP_INIT);
9862ffc8bcaSDan McDonald
9872ffc8bcaSDan McDonald con_log(CL_ANN1, (CE_CONT, "[CMD]%x", mfiFrameInit2->cmd));
9882ffc8bcaSDan McDonald
9892ffc8bcaSDan McDonald ddi_put8(instance->mpi2_frame_pool_dma_obj.acc_handle,
9902ffc8bcaSDan McDonald &mfiFrameInit2->cmd_status,
9912ffc8bcaSDan McDonald MFI_STAT_INVALID_STATUS);
9922ffc8bcaSDan McDonald
9932ffc8bcaSDan McDonald con_log(CL_ANN1, (CE_CONT, "[Status]%x", mfiFrameInit2->cmd_status));
9942ffc8bcaSDan McDonald
9952ffc8bcaSDan McDonald ddi_put32(instance->mpi2_frame_pool_dma_obj.acc_handle,
9962ffc8bcaSDan McDonald &mfiFrameInit2->queue_info_new_phys_addr_lo,
9972ffc8bcaSDan McDonald mpi2_dma_obj->dma_cookie[0].dmac_address);
9982ffc8bcaSDan McDonald
9992ffc8bcaSDan McDonald ddi_put32(instance->mpi2_frame_pool_dma_obj.acc_handle,
10002ffc8bcaSDan McDonald &mfiFrameInit2->data_xfer_len,
10012ffc8bcaSDan McDonald sizeof (Mpi2IOCInitRequest_t));
10022ffc8bcaSDan McDonald
10032ffc8bcaSDan McDonald con_log(CL_ANN1, (CE_CONT, "[reply q desc addr]%x",
10042ffc8bcaSDan McDonald (int)init->ReplyDescriptorPostQueueAddress));
10052ffc8bcaSDan McDonald
10062ffc8bcaSDan McDonald /* fill driver version information */
10072ffc8bcaSDan McDonald fill_up_drv_ver(&drv_ver_info);
10082ffc8bcaSDan McDonald
10092ffc8bcaSDan McDonald /* allocate the driver version data transfer buffer */
10102ffc8bcaSDan McDonald instance->drv_ver_dma_obj.size = sizeof (drv_ver_info.drv_ver);
10112ffc8bcaSDan McDonald instance->drv_ver_dma_obj.dma_attr = mrsas_generic_dma_attr;
10122ffc8bcaSDan McDonald instance->drv_ver_dma_obj.dma_attr.dma_attr_addr_hi = 0xFFFFFFFFU;
10132ffc8bcaSDan McDonald instance->drv_ver_dma_obj.dma_attr.dma_attr_count_max = 0xFFFFFFFFU;
10142ffc8bcaSDan McDonald instance->drv_ver_dma_obj.dma_attr.dma_attr_sgllen = 1;
10152ffc8bcaSDan McDonald instance->drv_ver_dma_obj.dma_attr.dma_attr_align = 1;
10162ffc8bcaSDan McDonald
10172ffc8bcaSDan McDonald if (mrsas_alloc_dma_obj(instance, &instance->drv_ver_dma_obj,
10182ffc8bcaSDan McDonald (uchar_t)DDI_STRUCTURE_LE_ACC) != 1) {
1019ff38cf9dSAndy Fiddaman dev_err(instance->dip, CE_WARN,
10202ffc8bcaSDan McDonald "fusion init: Could not allocate driver version buffer.");
10212ffc8bcaSDan McDonald return (DDI_FAILURE);
10222ffc8bcaSDan McDonald }
10232ffc8bcaSDan McDonald /* copy driver version to dma buffer */
10242ffc8bcaSDan McDonald bzero(instance->drv_ver_dma_obj.buffer, sizeof (drv_ver_info.drv_ver));
10252ffc8bcaSDan McDonald ddi_rep_put8(cmd->frame_dma_obj.acc_handle,
10262ffc8bcaSDan McDonald (uint8_t *)drv_ver_info.drv_ver,
10272ffc8bcaSDan McDonald (uint8_t *)instance->drv_ver_dma_obj.buffer,
10282ffc8bcaSDan McDonald sizeof (drv_ver_info.drv_ver), DDI_DEV_AUTOINCR);
10292ffc8bcaSDan McDonald
10302ffc8bcaSDan McDonald /* send driver version physical address to firmware */
10312ffc8bcaSDan McDonald ddi_put64(cmd->frame_dma_obj.acc_handle, &mfiFrameInit2->driverversion,
10322ffc8bcaSDan McDonald instance->drv_ver_dma_obj.dma_cookie[0].dmac_address);
10332ffc8bcaSDan McDonald
10342ffc8bcaSDan McDonald con_log(CL_ANN1, (CE_CONT, "[MPIINIT2 frame Phys addr ]0x%x len = %x",
10352ffc8bcaSDan McDonald mfiFrameInit2->queue_info_new_phys_addr_lo,
10362ffc8bcaSDan McDonald (int)sizeof (Mpi2IOCInitRequest_t)));
10372ffc8bcaSDan McDonald
10382ffc8bcaSDan McDonald con_log(CL_ANN1, (CE_CONT, "[Length]%x", mfiFrameInit2->data_xfer_len));
10392ffc8bcaSDan McDonald
10402ffc8bcaSDan McDonald con_log(CL_ANN1, (CE_CONT, "[MFI frame Phys Address]%x len = %x",
10412ffc8bcaSDan McDonald cmd->scsi_io_request_phys_addr,
10422ffc8bcaSDan McDonald (int)sizeof (struct mrsas_init_frame2)));
10432ffc8bcaSDan McDonald
10442ffc8bcaSDan McDonald /* disable interrupts before sending INIT2 frame */
10452ffc8bcaSDan McDonald instance->func_ptr->disable_intr(instance);
10462ffc8bcaSDan McDonald
10474bc492d2SAndy Fiddaman req_desc.Words = cmd->scsi_io_request_phys_addr;
10484bc492d2SAndy Fiddaman req_desc.MFAIo.RequestFlags =
10492ffc8bcaSDan McDonald (MPI2_REQ_DESCRIPT_FLAGS_MFA << MPI2_REQ_DESCRIPT_FLAGS_TYPE_SHIFT);
10502ffc8bcaSDan McDonald
10514bc492d2SAndy Fiddaman cmd->request_desc = &req_desc;
10522ffc8bcaSDan McDonald
10532ffc8bcaSDan McDonald /* issue the init frame */
10544bc492d2SAndy Fiddaman
10554bc492d2SAndy Fiddaman mutex_enter(&instance->reg_write_mtx);
10564bc492d2SAndy Fiddaman WR_IB_LOW_QPORT((uint32_t)(req_desc.Words), instance);
10574bc492d2SAndy Fiddaman WR_IB_HIGH_QPORT((uint32_t)(req_desc.Words >> 32), instance);
10584bc492d2SAndy Fiddaman mutex_exit(&instance->reg_write_mtx);
10592ffc8bcaSDan McDonald
10602ffc8bcaSDan McDonald con_log(CL_ANN1, (CE_CONT, "[cmd = %d] ", frame_hdr->cmd));
10612ffc8bcaSDan McDonald con_log(CL_ANN1, (CE_CONT, "[cmd Status= %x] ",
10622ffc8bcaSDan McDonald frame_hdr->cmd_status));
10632ffc8bcaSDan McDonald
10644bc492d2SAndy Fiddaman timeout = drv_usectohz(MFI_POLL_TIMEOUT_SECS * MICROSEC);
10654bc492d2SAndy Fiddaman do {
10664bc492d2SAndy Fiddaman if (ddi_get8(cmd->frame_dma_obj.acc_handle,
10674bc492d2SAndy Fiddaman &mfiFrameInit2->cmd_status) != MFI_CMD_STATUS_POLL_MODE)
10684bc492d2SAndy Fiddaman break;
10694bc492d2SAndy Fiddaman delay(1);
10704bc492d2SAndy Fiddaman timeout--;
10714bc492d2SAndy Fiddaman } while (timeout > 0);
10724bc492d2SAndy Fiddaman
10732ffc8bcaSDan McDonald if (ddi_get8(instance->mpi2_frame_pool_dma_obj.acc_handle,
10742ffc8bcaSDan McDonald &mfiFrameInit2->cmd_status) == 0) {
10752ffc8bcaSDan McDonald con_log(CL_ANN, (CE_NOTE, "INIT2 Success"));
10762ffc8bcaSDan McDonald } else {
10772ffc8bcaSDan McDonald con_log(CL_ANN, (CE_WARN, "INIT2 Fail"));
10782ffc8bcaSDan McDonald mrsas_dump_reply_desc(instance);
10792ffc8bcaSDan McDonald goto fail_ioc_init;
10802ffc8bcaSDan McDonald }
10812ffc8bcaSDan McDonald
10822ffc8bcaSDan McDonald mrsas_dump_reply_desc(instance);
10832ffc8bcaSDan McDonald
10842ffc8bcaSDan McDonald instance->unroll.verBuff = 1;
10852ffc8bcaSDan McDonald
10862ffc8bcaSDan McDonald con_log(CL_ANN, (CE_NOTE, "mrsas_tbolt_ioc_init: SUCCESSFUL"));
10872ffc8bcaSDan McDonald
10882ffc8bcaSDan McDonald return (DDI_SUCCESS);
10892ffc8bcaSDan McDonald
10902ffc8bcaSDan McDonald
10912ffc8bcaSDan McDonald fail_ioc_init:
10922ffc8bcaSDan McDonald
10932ffc8bcaSDan McDonald (void) mrsas_free_dma_obj(instance, instance->drv_ver_dma_obj);
10942ffc8bcaSDan McDonald
10952ffc8bcaSDan McDonald return (DDI_FAILURE);
10962ffc8bcaSDan McDonald }
10972ffc8bcaSDan McDonald
10982ffc8bcaSDan McDonald int
wait_for_outstanding_poll_io(struct mrsas_instance * instance)10992ffc8bcaSDan McDonald wait_for_outstanding_poll_io(struct mrsas_instance *instance)
11002ffc8bcaSDan McDonald {
11012ffc8bcaSDan McDonald int i;
11022ffc8bcaSDan McDonald uint32_t wait_time = dump_io_wait_time;
11032ffc8bcaSDan McDonald for (i = 0; i < wait_time; i++) {
11042ffc8bcaSDan McDonald /*
11052ffc8bcaSDan McDonald * Check For Outstanding poll Commands
11062ffc8bcaSDan McDonald * except ldsync command and aen command
11072ffc8bcaSDan McDonald */
11082ffc8bcaSDan McDonald if (instance->fw_outstanding <= 2) {
11092ffc8bcaSDan McDonald break;
11102ffc8bcaSDan McDonald }
1111d8873b31SJoyce McIntosh drv_usecwait(MILLISEC);
11122ffc8bcaSDan McDonald /* complete commands from reply queue */
11132ffc8bcaSDan McDonald (void) mr_sas_tbolt_process_outstanding_cmd(instance);
11142ffc8bcaSDan McDonald }
11152ffc8bcaSDan McDonald if (instance->fw_outstanding > 2) {
11162ffc8bcaSDan McDonald return (1);
11172ffc8bcaSDan McDonald }
11182ffc8bcaSDan McDonald return (0);
11192ffc8bcaSDan McDonald }
11202ffc8bcaSDan McDonald /*
11212ffc8bcaSDan McDonald * scsi_pkt handling
11222ffc8bcaSDan McDonald *
11232ffc8bcaSDan McDonald * Visible to the external world via the transport structure.
11242ffc8bcaSDan McDonald */
11252ffc8bcaSDan McDonald
11262ffc8bcaSDan McDonald int
mrsas_tbolt_tran_start(struct scsi_address * ap,struct scsi_pkt * pkt)11272ffc8bcaSDan McDonald mrsas_tbolt_tran_start(struct scsi_address *ap, struct scsi_pkt *pkt)
11282ffc8bcaSDan McDonald {
11292ffc8bcaSDan McDonald struct mrsas_instance *instance = ADDR2MR(ap);
11302ffc8bcaSDan McDonald struct scsa_cmd *acmd = PKT2CMD(pkt);
11312ffc8bcaSDan McDonald struct mrsas_cmd *cmd = NULL;
11322ffc8bcaSDan McDonald uchar_t cmd_done = 0;
11332ffc8bcaSDan McDonald
11342ffc8bcaSDan McDonald con_log(CL_DLEVEL1, (CE_NOTE, "chkpnt:%s:%d", __func__, __LINE__));
11352ffc8bcaSDan McDonald if (instance->deadadapter == 1) {
1136ff38cf9dSAndy Fiddaman dev_err(instance->dip, CE_WARN,
11372ffc8bcaSDan McDonald "mrsas_tran_start:TBOLT return TRAN_FATAL_ERROR "
11382ffc8bcaSDan McDonald "for IO, as the HBA doesnt take any more IOs");
11392ffc8bcaSDan McDonald if (pkt) {
11402ffc8bcaSDan McDonald pkt->pkt_reason = CMD_DEV_GONE;
11412ffc8bcaSDan McDonald pkt->pkt_statistics = STAT_DISCON;
11422ffc8bcaSDan McDonald }
11432ffc8bcaSDan McDonald return (TRAN_FATAL_ERROR);
11442ffc8bcaSDan McDonald }
11452ffc8bcaSDan McDonald if (instance->adapterresetinprogress) {
11462ffc8bcaSDan McDonald con_log(CL_ANN, (CE_NOTE, "Reset flag set, "
11472ffc8bcaSDan McDonald "returning mfi_pkt and setting TRAN_BUSY\n"));
11482ffc8bcaSDan McDonald return (TRAN_BUSY);
11492ffc8bcaSDan McDonald }
11502ffc8bcaSDan McDonald (void) mrsas_tbolt_prepare_pkt(acmd);
11512ffc8bcaSDan McDonald
11522ffc8bcaSDan McDonald cmd = mrsas_tbolt_build_cmd(instance, ap, pkt, &cmd_done);
11532ffc8bcaSDan McDonald
11542ffc8bcaSDan McDonald /*
11552ffc8bcaSDan McDonald * Check if the command is already completed by the mrsas_build_cmd()
11562ffc8bcaSDan McDonald * routine. In which case the busy_flag would be clear and scb will be
11572ffc8bcaSDan McDonald * NULL and appropriate reason provided in pkt_reason field
11582ffc8bcaSDan McDonald */
11592ffc8bcaSDan McDonald if (cmd_done) {
11602ffc8bcaSDan McDonald pkt->pkt_reason = CMD_CMPLT;
11612ffc8bcaSDan McDonald pkt->pkt_scbp[0] = STATUS_GOOD;
11622ffc8bcaSDan McDonald pkt->pkt_state |= STATE_GOT_BUS | STATE_GOT_TARGET
11632ffc8bcaSDan McDonald | STATE_SENT_CMD;
11642ffc8bcaSDan McDonald if (((pkt->pkt_flags & FLAG_NOINTR) == 0) && pkt->pkt_comp) {
11652ffc8bcaSDan McDonald (*pkt->pkt_comp)(pkt);
11662ffc8bcaSDan McDonald }
11672ffc8bcaSDan McDonald
11682ffc8bcaSDan McDonald return (TRAN_ACCEPT);
11692ffc8bcaSDan McDonald }
11702ffc8bcaSDan McDonald
11712ffc8bcaSDan McDonald if (cmd == NULL) {
11722ffc8bcaSDan McDonald return (TRAN_BUSY);
11732ffc8bcaSDan McDonald }
11742ffc8bcaSDan McDonald
11752ffc8bcaSDan McDonald
11762ffc8bcaSDan McDonald if ((pkt->pkt_flags & FLAG_NOINTR) == 0) {
11772ffc8bcaSDan McDonald if (instance->fw_outstanding > instance->max_fw_cmds) {
1178ff38cf9dSAndy Fiddaman dev_err(instance->dip, CE_WARN,
11792ffc8bcaSDan McDonald "Command Queue Full... Returning BUSY");
1180091932b4SAndy Fiddaman DTRACE_PROBE2(tbolt_start_tran_err,
1181091932b4SAndy Fiddaman uint16_t, instance->fw_outstanding,
1182091932b4SAndy Fiddaman uint16_t, instance->max_fw_cmds);
11832ffc8bcaSDan McDonald return_raid_msg_pkt(instance, cmd);
11842ffc8bcaSDan McDonald return (TRAN_BUSY);
11852ffc8bcaSDan McDonald }
11862ffc8bcaSDan McDonald
11872ffc8bcaSDan McDonald /* Synchronize the Cmd frame for the controller */
11882ffc8bcaSDan McDonald (void) ddi_dma_sync(cmd->frame_dma_obj.dma_handle, 0, 0,
11892ffc8bcaSDan McDonald DDI_DMA_SYNC_FORDEV);
11902ffc8bcaSDan McDonald
11912ffc8bcaSDan McDonald con_log(CL_ANN, (CE_CONT, "tbolt_issue_cmd: SCSI CDB[0]=0x%x "
11922ffc8bcaSDan McDonald "cmd->index:0x%x SMID 0x%x\n", pkt->pkt_cdbp[0],
11932ffc8bcaSDan McDonald cmd->index, cmd->SMID));
11942ffc8bcaSDan McDonald
11952ffc8bcaSDan McDonald instance->func_ptr->issue_cmd(cmd, instance);
11962ffc8bcaSDan McDonald } else {
11972ffc8bcaSDan McDonald instance->func_ptr->issue_cmd(cmd, instance);
11982ffc8bcaSDan McDonald (void) wait_for_outstanding_poll_io(instance);
11992ffc8bcaSDan McDonald (void) mrsas_common_check(instance, cmd);
1200091932b4SAndy Fiddaman DTRACE_PROBE2(tbolt_start_nointr_done,
1201091932b4SAndy Fiddaman uint8_t, cmd->frame->hdr.cmd,
1202091932b4SAndy Fiddaman uint8_t, cmd->frame->hdr.cmd_status);
12032ffc8bcaSDan McDonald }
12042ffc8bcaSDan McDonald
12052ffc8bcaSDan McDonald return (TRAN_ACCEPT);
12062ffc8bcaSDan McDonald }
12072ffc8bcaSDan McDonald
12082ffc8bcaSDan McDonald /*
12092ffc8bcaSDan McDonald * prepare the pkt:
12102ffc8bcaSDan McDonald * the pkt may have been resubmitted or just reused so
12112ffc8bcaSDan McDonald * initialize some fields and do some checks.
12122ffc8bcaSDan McDonald */
12132ffc8bcaSDan McDonald static int
mrsas_tbolt_prepare_pkt(struct scsa_cmd * acmd)12142ffc8bcaSDan McDonald mrsas_tbolt_prepare_pkt(struct scsa_cmd *acmd)
12152ffc8bcaSDan McDonald {
12162ffc8bcaSDan McDonald struct scsi_pkt *pkt = CMD2PKT(acmd);
12172ffc8bcaSDan McDonald
12182ffc8bcaSDan McDonald
12192ffc8bcaSDan McDonald /*
12202ffc8bcaSDan McDonald * Reinitialize some fields that need it; the packet may
12212ffc8bcaSDan McDonald * have been resubmitted
12222ffc8bcaSDan McDonald */
12232ffc8bcaSDan McDonald pkt->pkt_reason = CMD_CMPLT;
12242ffc8bcaSDan McDonald pkt->pkt_state = 0;
12252ffc8bcaSDan McDonald pkt->pkt_statistics = 0;
12262ffc8bcaSDan McDonald pkt->pkt_resid = 0;
12272ffc8bcaSDan McDonald
12282ffc8bcaSDan McDonald /*
12292ffc8bcaSDan McDonald * zero status byte.
12302ffc8bcaSDan McDonald */
12312ffc8bcaSDan McDonald *(pkt->pkt_scbp) = 0;
12322ffc8bcaSDan McDonald
12332ffc8bcaSDan McDonald return (0);
12342ffc8bcaSDan McDonald }
12352ffc8bcaSDan McDonald
12362ffc8bcaSDan McDonald
12372ffc8bcaSDan McDonald int
mr_sas_tbolt_build_sgl(struct mrsas_instance * instance,struct scsa_cmd * acmd,struct mrsas_cmd * cmd,Mpi2RaidSCSIIORequest_t * scsi_raid_io,uint32_t * datalen)12382ffc8bcaSDan McDonald mr_sas_tbolt_build_sgl(struct mrsas_instance *instance,
12392ffc8bcaSDan McDonald struct scsa_cmd *acmd,
12402ffc8bcaSDan McDonald struct mrsas_cmd *cmd,
12412ffc8bcaSDan McDonald Mpi2RaidSCSIIORequest_t *scsi_raid_io,
12422ffc8bcaSDan McDonald uint32_t *datalen)
12432ffc8bcaSDan McDonald {
12442ffc8bcaSDan McDonald uint32_t MaxSGEs;
12452ffc8bcaSDan McDonald int sg_to_process;
12462ffc8bcaSDan McDonald uint32_t i, j;
12472ffc8bcaSDan McDonald uint32_t numElements, endElement;
12482ffc8bcaSDan McDonald Mpi25IeeeSgeChain64_t *ieeeChainElement = NULL;
12492ffc8bcaSDan McDonald Mpi25IeeeSgeChain64_t *scsi_raid_io_sgl_ieee = NULL;
12502ffc8bcaSDan McDonald ddi_acc_handle_t acc_handle =
12512ffc8bcaSDan McDonald instance->mpi2_frame_pool_dma_obj.acc_handle;
12522ffc8bcaSDan McDonald
12532ffc8bcaSDan McDonald con_log(CL_ANN1, (CE_NOTE,
12542ffc8bcaSDan McDonald "chkpnt: Building Chained SGL :%d", __LINE__));
12552ffc8bcaSDan McDonald
12562ffc8bcaSDan McDonald /* Calulate SGE size in number of Words(32bit) */
12572ffc8bcaSDan McDonald /* Clear the datalen before updating it. */
12582ffc8bcaSDan McDonald *datalen = 0;
12592ffc8bcaSDan McDonald
12602ffc8bcaSDan McDonald MaxSGEs = instance->max_sge_in_main_msg;
12612ffc8bcaSDan McDonald
12622ffc8bcaSDan McDonald ddi_put16(acc_handle, &scsi_raid_io->SGLFlags,
12632ffc8bcaSDan McDonald MPI2_SGE_FLAGS_64_BIT_ADDRESSING);
12642ffc8bcaSDan McDonald
12652ffc8bcaSDan McDonald /* set data transfer flag. */
12662ffc8bcaSDan McDonald if (acmd->cmd_flags & CFLAG_DMASEND) {
12672ffc8bcaSDan McDonald ddi_put32(acc_handle, &scsi_raid_io->Control,
12682ffc8bcaSDan McDonald MPI2_SCSIIO_CONTROL_WRITE);
12692ffc8bcaSDan McDonald } else {
12702ffc8bcaSDan McDonald ddi_put32(acc_handle, &scsi_raid_io->Control,
12712ffc8bcaSDan McDonald MPI2_SCSIIO_CONTROL_READ);
12722ffc8bcaSDan McDonald }
12732ffc8bcaSDan McDonald
12742ffc8bcaSDan McDonald
12752ffc8bcaSDan McDonald numElements = acmd->cmd_cookiecnt;
12762ffc8bcaSDan McDonald
12772ffc8bcaSDan McDonald con_log(CL_DLEVEL1, (CE_NOTE, "[SGE Count]:%x", numElements));
12782ffc8bcaSDan McDonald
12792ffc8bcaSDan McDonald if (numElements > instance->max_num_sge) {
12802ffc8bcaSDan McDonald con_log(CL_ANN, (CE_NOTE,
12812ffc8bcaSDan McDonald "[Max SGE Count Exceeded]:%x", numElements));
12822ffc8bcaSDan McDonald return (numElements);
12832ffc8bcaSDan McDonald }
12842ffc8bcaSDan McDonald
12852ffc8bcaSDan McDonald ddi_put8(acc_handle, &scsi_raid_io->RaidContext.numSGE,
12862ffc8bcaSDan McDonald (uint8_t)numElements);
12872ffc8bcaSDan McDonald
12882ffc8bcaSDan McDonald /* set end element in main message frame */
12892ffc8bcaSDan McDonald endElement = (numElements <= MaxSGEs) ? numElements : (MaxSGEs - 1);
12902ffc8bcaSDan McDonald
12912ffc8bcaSDan McDonald /* prepare the scatter-gather list for the firmware */
12922ffc8bcaSDan McDonald scsi_raid_io_sgl_ieee =
12932ffc8bcaSDan McDonald (Mpi25IeeeSgeChain64_t *)&scsi_raid_io->SGL.IeeeChain;
12942ffc8bcaSDan McDonald
1295df950592SHummyPkg if (instance->gen3) {
12962ffc8bcaSDan McDonald Mpi25IeeeSgeChain64_t *sgl_ptr_end = scsi_raid_io_sgl_ieee;
12972ffc8bcaSDan McDonald sgl_ptr_end += instance->max_sge_in_main_msg - 1;
12982ffc8bcaSDan McDonald
12992ffc8bcaSDan McDonald ddi_put8(acc_handle, &sgl_ptr_end->Flags, 0);
13002ffc8bcaSDan McDonald }
13012ffc8bcaSDan McDonald
13022ffc8bcaSDan McDonald for (i = 0; i < endElement; i++, scsi_raid_io_sgl_ieee++) {
13032ffc8bcaSDan McDonald ddi_put64(acc_handle, &scsi_raid_io_sgl_ieee->Address,
13042ffc8bcaSDan McDonald acmd->cmd_dmacookies[i].dmac_laddress);
13052ffc8bcaSDan McDonald
13062ffc8bcaSDan McDonald ddi_put32(acc_handle, &scsi_raid_io_sgl_ieee->Length,
13072ffc8bcaSDan McDonald acmd->cmd_dmacookies[i].dmac_size);
13082ffc8bcaSDan McDonald
13092ffc8bcaSDan McDonald ddi_put8(acc_handle, &scsi_raid_io_sgl_ieee->Flags, 0);
13102ffc8bcaSDan McDonald
1311df950592SHummyPkg if (instance->gen3) {
13122ffc8bcaSDan McDonald if (i == (numElements - 1)) {
13132ffc8bcaSDan McDonald ddi_put8(acc_handle,
13142ffc8bcaSDan McDonald &scsi_raid_io_sgl_ieee->Flags,
13152ffc8bcaSDan McDonald IEEE_SGE_FLAGS_END_OF_LIST);
13162ffc8bcaSDan McDonald }
13172ffc8bcaSDan McDonald }
13182ffc8bcaSDan McDonald
13192ffc8bcaSDan McDonald *datalen += acmd->cmd_dmacookies[i].dmac_size;
13202ffc8bcaSDan McDonald
13212ffc8bcaSDan McDonald #ifdef DEBUG
13222ffc8bcaSDan McDonald con_log(CL_DLEVEL1, (CE_NOTE, "[SGL Address]: %" PRIx64,
13232ffc8bcaSDan McDonald scsi_raid_io_sgl_ieee->Address));
13242ffc8bcaSDan McDonald con_log(CL_DLEVEL1, (CE_NOTE, "[SGL Length]:%x",
13252ffc8bcaSDan McDonald scsi_raid_io_sgl_ieee->Length));
13262ffc8bcaSDan McDonald con_log(CL_DLEVEL1, (CE_NOTE, "[SGL Flags]:%x",
13272ffc8bcaSDan McDonald scsi_raid_io_sgl_ieee->Flags));
13282ffc8bcaSDan McDonald #endif
13292ffc8bcaSDan McDonald
13302ffc8bcaSDan McDonald }
13312ffc8bcaSDan McDonald
13322ffc8bcaSDan McDonald ddi_put8(acc_handle, &scsi_raid_io->ChainOffset, 0);
13332ffc8bcaSDan McDonald
13342ffc8bcaSDan McDonald /* check if chained SGL required */
13352ffc8bcaSDan McDonald if (i < numElements) {
13362ffc8bcaSDan McDonald
13372ffc8bcaSDan McDonald con_log(CL_ANN1, (CE_NOTE, "[Chain Element index]:%x", i));
13382ffc8bcaSDan McDonald
1339df950592SHummyPkg if (instance->gen3) {
13402ffc8bcaSDan McDonald uint16_t ioFlags =
13412ffc8bcaSDan McDonald ddi_get16(acc_handle, &scsi_raid_io->IoFlags);
13422ffc8bcaSDan McDonald
13432ffc8bcaSDan McDonald if ((ioFlags &
13442ffc8bcaSDan McDonald MPI25_SAS_DEVICE0_FLAGS_ENABLED_FAST_PATH) !=
13452ffc8bcaSDan McDonald MPI25_SAS_DEVICE0_FLAGS_ENABLED_FAST_PATH) {
13462ffc8bcaSDan McDonald ddi_put8(acc_handle, &scsi_raid_io->ChainOffset,
13472ffc8bcaSDan McDonald (U8)instance->chain_offset_io_req);
13482ffc8bcaSDan McDonald } else {
13492ffc8bcaSDan McDonald ddi_put8(acc_handle,
13502ffc8bcaSDan McDonald &scsi_raid_io->ChainOffset, 0);
13512ffc8bcaSDan McDonald }
13522ffc8bcaSDan McDonald } else {
13532ffc8bcaSDan McDonald ddi_put8(acc_handle, &scsi_raid_io->ChainOffset,
13542ffc8bcaSDan McDonald (U8)instance->chain_offset_io_req);
13552ffc8bcaSDan McDonald }
13562ffc8bcaSDan McDonald
13572ffc8bcaSDan McDonald /* prepare physical chain element */
13582ffc8bcaSDan McDonald ieeeChainElement = scsi_raid_io_sgl_ieee;
13592ffc8bcaSDan McDonald
13602ffc8bcaSDan McDonald ddi_put8(acc_handle, &ieeeChainElement->NextChainOffset, 0);
13612ffc8bcaSDan McDonald
1362df950592SHummyPkg if (instance->gen3) {
13632ffc8bcaSDan McDonald ddi_put8(acc_handle, &ieeeChainElement->Flags,
13642ffc8bcaSDan McDonald IEEE_SGE_FLAGS_CHAIN_ELEMENT);
13652ffc8bcaSDan McDonald } else {
13662ffc8bcaSDan McDonald ddi_put8(acc_handle, &ieeeChainElement->Flags,
13672ffc8bcaSDan McDonald (IEEE_SGE_FLAGS_CHAIN_ELEMENT |
13682ffc8bcaSDan McDonald MPI2_IEEE_SGE_FLAGS_IOCPLBNTA_ADDR));
13692ffc8bcaSDan McDonald }
13702ffc8bcaSDan McDonald
13712ffc8bcaSDan McDonald ddi_put32(acc_handle, &ieeeChainElement->Length,
13722ffc8bcaSDan McDonald (sizeof (MPI2_SGE_IO_UNION) * (numElements - i)));
13732ffc8bcaSDan McDonald
13742ffc8bcaSDan McDonald ddi_put64(acc_handle, &ieeeChainElement->Address,
13752ffc8bcaSDan McDonald (U64)cmd->sgl_phys_addr);
13762ffc8bcaSDan McDonald
13772ffc8bcaSDan McDonald sg_to_process = numElements - i;
13782ffc8bcaSDan McDonald
13792ffc8bcaSDan McDonald con_log(CL_ANN1, (CE_NOTE,
13802ffc8bcaSDan McDonald "[Additional SGE Count]:%x", endElement));
13812ffc8bcaSDan McDonald
13822ffc8bcaSDan McDonald /* point to the chained SGL buffer */
13832ffc8bcaSDan McDonald scsi_raid_io_sgl_ieee = (Mpi25IeeeSgeChain64_t *)cmd->sgl;
13842ffc8bcaSDan McDonald
13852ffc8bcaSDan McDonald /* build rest of the SGL in chained buffer */
13862ffc8bcaSDan McDonald for (j = 0; j < sg_to_process; j++, scsi_raid_io_sgl_ieee++) {
13872ffc8bcaSDan McDonald con_log(CL_DLEVEL3, (CE_NOTE, "[remaining SGL]:%x", i));
13882ffc8bcaSDan McDonald
13892ffc8bcaSDan McDonald ddi_put64(acc_handle, &scsi_raid_io_sgl_ieee->Address,
13902ffc8bcaSDan McDonald acmd->cmd_dmacookies[i].dmac_laddress);
13912ffc8bcaSDan McDonald
13922ffc8bcaSDan McDonald ddi_put32(acc_handle, &scsi_raid_io_sgl_ieee->Length,
13932ffc8bcaSDan McDonald acmd->cmd_dmacookies[i].dmac_size);
13942ffc8bcaSDan McDonald
13952ffc8bcaSDan McDonald ddi_put8(acc_handle, &scsi_raid_io_sgl_ieee->Flags, 0);
13962ffc8bcaSDan McDonald
1397df950592SHummyPkg if (instance->gen3) {
13982ffc8bcaSDan McDonald if (i == (numElements - 1)) {
13992ffc8bcaSDan McDonald ddi_put8(acc_handle,
14002ffc8bcaSDan McDonald &scsi_raid_io_sgl_ieee->Flags,
14012ffc8bcaSDan McDonald IEEE_SGE_FLAGS_END_OF_LIST);
14022ffc8bcaSDan McDonald }
14032ffc8bcaSDan McDonald }
14042ffc8bcaSDan McDonald
14052ffc8bcaSDan McDonald *datalen += acmd->cmd_dmacookies[i].dmac_size;
14062ffc8bcaSDan McDonald
14072ffc8bcaSDan McDonald #if DEBUG
14082ffc8bcaSDan McDonald con_log(CL_DLEVEL1, (CE_NOTE,
14092ffc8bcaSDan McDonald "[SGL Address]: %" PRIx64,
14102ffc8bcaSDan McDonald scsi_raid_io_sgl_ieee->Address));
14112ffc8bcaSDan McDonald con_log(CL_DLEVEL1, (CE_NOTE,
14122ffc8bcaSDan McDonald "[SGL Length]:%x", scsi_raid_io_sgl_ieee->Length));
14132ffc8bcaSDan McDonald con_log(CL_DLEVEL1, (CE_NOTE,
14142ffc8bcaSDan McDonald "[SGL Flags]:%x", scsi_raid_io_sgl_ieee->Flags));
14152ffc8bcaSDan McDonald #endif
14162ffc8bcaSDan McDonald
14172ffc8bcaSDan McDonald i++;
14182ffc8bcaSDan McDonald }
14192ffc8bcaSDan McDonald }
14202ffc8bcaSDan McDonald
14212ffc8bcaSDan McDonald return (0);
14222ffc8bcaSDan McDonald } /*end of BuildScatterGather */
14232ffc8bcaSDan McDonald
14242ffc8bcaSDan McDonald
14252ffc8bcaSDan McDonald /*
14262ffc8bcaSDan McDonald * build_cmd
14272ffc8bcaSDan McDonald */
14282ffc8bcaSDan McDonald static struct mrsas_cmd *
mrsas_tbolt_build_cmd(struct mrsas_instance * instance,struct scsi_address * ap,struct scsi_pkt * pkt,uchar_t * cmd_done)14292ffc8bcaSDan McDonald mrsas_tbolt_build_cmd(struct mrsas_instance *instance, struct scsi_address *ap,
14302ffc8bcaSDan McDonald struct scsi_pkt *pkt, uchar_t *cmd_done)
14312ffc8bcaSDan McDonald {
14322ffc8bcaSDan McDonald uint8_t fp_possible = 0;
14332ffc8bcaSDan McDonald uint32_t index;
14342ffc8bcaSDan McDonald uint32_t lba_count = 0;
14352ffc8bcaSDan McDonald uint32_t start_lba_hi = 0;
14362ffc8bcaSDan McDonald uint32_t start_lba_lo = 0;
14372ffc8bcaSDan McDonald ddi_acc_handle_t acc_handle =
14382ffc8bcaSDan McDonald instance->mpi2_frame_pool_dma_obj.acc_handle;
14392ffc8bcaSDan McDonald struct mrsas_cmd *cmd = NULL;
14402ffc8bcaSDan McDonald struct scsa_cmd *acmd = PKT2CMD(pkt);
14412ffc8bcaSDan McDonald MRSAS_REQUEST_DESCRIPTOR_UNION *ReqDescUnion;
14422ffc8bcaSDan McDonald Mpi2RaidSCSIIORequest_t *scsi_raid_io;
14432ffc8bcaSDan McDonald uint32_t datalen;
14442ffc8bcaSDan McDonald struct IO_REQUEST_INFO io_info;
14452ffc8bcaSDan McDonald MR_FW_RAID_MAP_ALL *local_map_ptr;
14462ffc8bcaSDan McDonald uint16_t pd_cmd_cdblen;
14472ffc8bcaSDan McDonald
14482ffc8bcaSDan McDonald con_log(CL_DLEVEL1, (CE_NOTE,
14492ffc8bcaSDan McDonald "chkpnt: Entered mrsas_tbolt_build_cmd:%d", __LINE__));
14502ffc8bcaSDan McDonald
14512ffc8bcaSDan McDonald /* find out if this is logical or physical drive command. */
14522ffc8bcaSDan McDonald acmd->islogical = MRDRV_IS_LOGICAL(ap);
14532ffc8bcaSDan McDonald acmd->device_id = MAP_DEVICE_ID(instance, ap);
14542ffc8bcaSDan McDonald
14552ffc8bcaSDan McDonald *cmd_done = 0;
14562ffc8bcaSDan McDonald
14572ffc8bcaSDan McDonald /* get the command packet */
14582ffc8bcaSDan McDonald if (!(cmd = get_raid_msg_pkt(instance))) {
1459091932b4SAndy Fiddaman DTRACE_PROBE2(tbolt_build_cmd_mfi_err, uint16_t,
1460091932b4SAndy Fiddaman instance->fw_outstanding, uint16_t, instance->max_fw_cmds);
14612ffc8bcaSDan McDonald return (NULL);
14622ffc8bcaSDan McDonald }
14632ffc8bcaSDan McDonald
14642ffc8bcaSDan McDonald index = cmd->index;
14652ffc8bcaSDan McDonald ReqDescUnion = mr_sas_get_request_descriptor(instance, index);
14662ffc8bcaSDan McDonald ReqDescUnion->Words = 0;
14672ffc8bcaSDan McDonald ReqDescUnion->SCSIIO.SMID = cmd->SMID;
14682ffc8bcaSDan McDonald ReqDescUnion->SCSIIO.RequestFlags =
14692ffc8bcaSDan McDonald (MPI2_REQ_DESCRIPT_FLAGS_LD_IO <<
14702ffc8bcaSDan McDonald MPI2_REQ_DESCRIPT_FLAGS_TYPE_SHIFT);
14712ffc8bcaSDan McDonald
14722ffc8bcaSDan McDonald
14732ffc8bcaSDan McDonald cmd->request_desc = ReqDescUnion;
14742ffc8bcaSDan McDonald cmd->pkt = pkt;
14752ffc8bcaSDan McDonald cmd->cmd = acmd;
14762ffc8bcaSDan McDonald
1477091932b4SAndy Fiddaman DTRACE_PROBE4(tbolt_build_cmd, uint8_t, pkt->pkt_cdbp[0],
1478091932b4SAndy Fiddaman ulong_t, acmd->cmd_dmacount, ulong_t, acmd->cmd_dma_len,
1479091932b4SAndy Fiddaman uint16_t, acmd->device_id);
1480091932b4SAndy Fiddaman
14812ffc8bcaSDan McDonald /* lets get the command directions */
14822ffc8bcaSDan McDonald if (acmd->cmd_flags & CFLAG_DMASEND) {
14832ffc8bcaSDan McDonald if (acmd->cmd_flags & CFLAG_CONSISTENT) {
14842ffc8bcaSDan McDonald (void) ddi_dma_sync(acmd->cmd_dmahandle,
14852ffc8bcaSDan McDonald acmd->cmd_dma_offset, acmd->cmd_dma_len,
14862ffc8bcaSDan McDonald DDI_DMA_SYNC_FORDEV);
14872ffc8bcaSDan McDonald }
14882ffc8bcaSDan McDonald } else if (acmd->cmd_flags & ~CFLAG_DMASEND) {
14892ffc8bcaSDan McDonald if (acmd->cmd_flags & CFLAG_CONSISTENT) {
14902ffc8bcaSDan McDonald (void) ddi_dma_sync(acmd->cmd_dmahandle,
14912ffc8bcaSDan McDonald acmd->cmd_dma_offset, acmd->cmd_dma_len,
14922ffc8bcaSDan McDonald DDI_DMA_SYNC_FORCPU);
14932ffc8bcaSDan McDonald }
14942ffc8bcaSDan McDonald } else {
14952ffc8bcaSDan McDonald con_log(CL_ANN, (CE_NOTE, "NO DMA"));
14962ffc8bcaSDan McDonald }
14972ffc8bcaSDan McDonald
14982ffc8bcaSDan McDonald
14992ffc8bcaSDan McDonald /* get SCSI_IO raid message frame pointer */
15002ffc8bcaSDan McDonald scsi_raid_io = (Mpi2RaidSCSIIORequest_t *)cmd->scsi_io_request;
15012ffc8bcaSDan McDonald
15022ffc8bcaSDan McDonald /* zero out SCSI_IO raid message frame */
15032ffc8bcaSDan McDonald bzero(scsi_raid_io, sizeof (Mpi2RaidSCSIIORequest_t));
15042ffc8bcaSDan McDonald
15052ffc8bcaSDan McDonald /* Set the ldTargetId set by BuildRaidContext() */
15062ffc8bcaSDan McDonald ddi_put16(acc_handle, &scsi_raid_io->RaidContext.ldTargetId,
15072ffc8bcaSDan McDonald acmd->device_id);
15082ffc8bcaSDan McDonald
15092ffc8bcaSDan McDonald /* Copy CDB to scsi_io_request message frame */
15102ffc8bcaSDan McDonald ddi_rep_put8(acc_handle,
15112ffc8bcaSDan McDonald (uint8_t *)pkt->pkt_cdbp, (uint8_t *)scsi_raid_io->CDB.CDB32,
15122ffc8bcaSDan McDonald acmd->cmd_cdblen, DDI_DEV_AUTOINCR);
15132ffc8bcaSDan McDonald
15142ffc8bcaSDan McDonald /*
15152ffc8bcaSDan McDonald * Just the CDB length, rest of the Flags are zero
15162ffc8bcaSDan McDonald * This will be modified later.
15172ffc8bcaSDan McDonald */
15182ffc8bcaSDan McDonald ddi_put16(acc_handle, &scsi_raid_io->IoFlags, acmd->cmd_cdblen);
15192ffc8bcaSDan McDonald
15202ffc8bcaSDan McDonald pd_cmd_cdblen = acmd->cmd_cdblen;
15212ffc8bcaSDan McDonald
1522e65bc174SAndy Fiddaman if (acmd->islogical) {
1523e65bc174SAndy Fiddaman
15242ffc8bcaSDan McDonald switch (pkt->pkt_cdbp[0]) {
15252ffc8bcaSDan McDonald case SCMD_READ:
15262ffc8bcaSDan McDonald case SCMD_WRITE:
15272ffc8bcaSDan McDonald case SCMD_READ_G1:
15282ffc8bcaSDan McDonald case SCMD_WRITE_G1:
15292ffc8bcaSDan McDonald case SCMD_READ_G4:
15302ffc8bcaSDan McDonald case SCMD_WRITE_G4:
15312ffc8bcaSDan McDonald case SCMD_READ_G5:
15322ffc8bcaSDan McDonald case SCMD_WRITE_G5:
15332ffc8bcaSDan McDonald
15342ffc8bcaSDan McDonald /* Initialize sense Information */
15352ffc8bcaSDan McDonald if (cmd->sense1 == NULL) {
15362ffc8bcaSDan McDonald con_log(CL_ANN, (CE_NOTE, "tbolt_build_cmd: "
15372ffc8bcaSDan McDonald "Sense buffer ptr NULL "));
15382ffc8bcaSDan McDonald }
15392ffc8bcaSDan McDonald bzero(cmd->sense1, SENSE_LENGTH);
15402ffc8bcaSDan McDonald con_log(CL_DLEVEL2, (CE_NOTE, "tbolt_build_cmd "
15412ffc8bcaSDan McDonald "CDB[0] = %x\n", pkt->pkt_cdbp[0]));
15422ffc8bcaSDan McDonald
15432ffc8bcaSDan McDonald if (acmd->cmd_cdblen == CDB_GROUP0) {
15442ffc8bcaSDan McDonald /* 6-byte cdb */
15452ffc8bcaSDan McDonald lba_count = (uint16_t)(pkt->pkt_cdbp[4]);
15462ffc8bcaSDan McDonald start_lba_lo = ((uint32_t)(pkt->pkt_cdbp[3]) |
15472ffc8bcaSDan McDonald ((uint32_t)(pkt->pkt_cdbp[2]) << 8) |
15482ffc8bcaSDan McDonald ((uint32_t)((pkt->pkt_cdbp[1]) & 0x1F)
15492ffc8bcaSDan McDonald << 16));
15502ffc8bcaSDan McDonald } else if (acmd->cmd_cdblen == CDB_GROUP1) {
15512ffc8bcaSDan McDonald /* 10-byte cdb */
15522ffc8bcaSDan McDonald lba_count =
15532ffc8bcaSDan McDonald (((uint16_t)(pkt->pkt_cdbp[8])) |
15542ffc8bcaSDan McDonald ((uint16_t)(pkt->pkt_cdbp[7]) << 8));
15552ffc8bcaSDan McDonald
15562ffc8bcaSDan McDonald start_lba_lo =
15572ffc8bcaSDan McDonald (((uint32_t)(pkt->pkt_cdbp[5])) |
15582ffc8bcaSDan McDonald ((uint32_t)(pkt->pkt_cdbp[4]) << 8) |
15592ffc8bcaSDan McDonald ((uint32_t)(pkt->pkt_cdbp[3]) << 16) |
15602ffc8bcaSDan McDonald ((uint32_t)(pkt->pkt_cdbp[2]) << 24));
15612ffc8bcaSDan McDonald
15622ffc8bcaSDan McDonald } else if (acmd->cmd_cdblen == CDB_GROUP5) {
15632ffc8bcaSDan McDonald /* 12-byte cdb */
15642ffc8bcaSDan McDonald lba_count = (
15652ffc8bcaSDan McDonald ((uint32_t)(pkt->pkt_cdbp[9])) |
15662ffc8bcaSDan McDonald ((uint32_t)(pkt->pkt_cdbp[8]) << 8) |
15672ffc8bcaSDan McDonald ((uint32_t)(pkt->pkt_cdbp[7]) << 16) |
15682ffc8bcaSDan McDonald ((uint32_t)(pkt->pkt_cdbp[6]) << 24));
15692ffc8bcaSDan McDonald
15702ffc8bcaSDan McDonald start_lba_lo =
15712ffc8bcaSDan McDonald (((uint32_t)(pkt->pkt_cdbp[5])) |
15722ffc8bcaSDan McDonald ((uint32_t)(pkt->pkt_cdbp[4]) << 8) |
15732ffc8bcaSDan McDonald ((uint32_t)(pkt->pkt_cdbp[3]) << 16) |
15742ffc8bcaSDan McDonald ((uint32_t)(pkt->pkt_cdbp[2]) << 24));
15752ffc8bcaSDan McDonald
15762ffc8bcaSDan McDonald } else if (acmd->cmd_cdblen == CDB_GROUP4) {
15772ffc8bcaSDan McDonald /* 16-byte cdb */
15782ffc8bcaSDan McDonald lba_count = (
15792ffc8bcaSDan McDonald ((uint32_t)(pkt->pkt_cdbp[13])) |
15802ffc8bcaSDan McDonald ((uint32_t)(pkt->pkt_cdbp[12]) << 8) |
15812ffc8bcaSDan McDonald ((uint32_t)(pkt->pkt_cdbp[11]) << 16) |
15822ffc8bcaSDan McDonald ((uint32_t)(pkt->pkt_cdbp[10]) << 24));
15832ffc8bcaSDan McDonald
15842ffc8bcaSDan McDonald start_lba_lo = (
15852ffc8bcaSDan McDonald ((uint32_t)(pkt->pkt_cdbp[9])) |
15862ffc8bcaSDan McDonald ((uint32_t)(pkt->pkt_cdbp[8]) << 8) |
15872ffc8bcaSDan McDonald ((uint32_t)(pkt->pkt_cdbp[7]) << 16) |
15882ffc8bcaSDan McDonald ((uint32_t)(pkt->pkt_cdbp[6]) << 24));
15892ffc8bcaSDan McDonald
15902ffc8bcaSDan McDonald start_lba_hi = (
15912ffc8bcaSDan McDonald ((uint32_t)(pkt->pkt_cdbp[5])) |
15922ffc8bcaSDan McDonald ((uint32_t)(pkt->pkt_cdbp[4]) << 8) |
15932ffc8bcaSDan McDonald ((uint32_t)(pkt->pkt_cdbp[3]) << 16) |
15942ffc8bcaSDan McDonald ((uint32_t)(pkt->pkt_cdbp[2]) << 24));
15952ffc8bcaSDan McDonald }
15962ffc8bcaSDan McDonald
15972ffc8bcaSDan McDonald if (instance->tbolt &&
15982ffc8bcaSDan McDonald ((lba_count * 512) > mrsas_tbolt_max_cap_maxxfer)) {
1599ff38cf9dSAndy Fiddaman dev_err(instance->dip, CE_WARN,
1600ff38cf9dSAndy Fiddaman "IO SECTOR COUNT exceeds "
16012ffc8bcaSDan McDonald "controller limit 0x%x sectors",
16022ffc8bcaSDan McDonald lba_count);
16032ffc8bcaSDan McDonald }
16042ffc8bcaSDan McDonald
16052ffc8bcaSDan McDonald bzero(&io_info, sizeof (struct IO_REQUEST_INFO));
16062ffc8bcaSDan McDonald io_info.ldStartBlock = ((uint64_t)start_lba_hi << 32) |
16072ffc8bcaSDan McDonald start_lba_lo;
16082ffc8bcaSDan McDonald io_info.numBlocks = lba_count;
16092ffc8bcaSDan McDonald io_info.ldTgtId = acmd->device_id;
16102ffc8bcaSDan McDonald
16112ffc8bcaSDan McDonald if (acmd->cmd_flags & CFLAG_DMASEND)
16122ffc8bcaSDan McDonald io_info.isRead = 0;
16132ffc8bcaSDan McDonald else
16142ffc8bcaSDan McDonald io_info.isRead = 1;
16152ffc8bcaSDan McDonald
16162ffc8bcaSDan McDonald
16172ffc8bcaSDan McDonald /* Acquire SYNC MAP UPDATE lock */
16182ffc8bcaSDan McDonald mutex_enter(&instance->sync_map_mtx);
16192ffc8bcaSDan McDonald
16202ffc8bcaSDan McDonald local_map_ptr =
16212ffc8bcaSDan McDonald instance->ld_map[(instance->map_id & 1)];
16222ffc8bcaSDan McDonald
16232ffc8bcaSDan McDonald if ((MR_TargetIdToLdGet(
16242ffc8bcaSDan McDonald acmd->device_id, local_map_ptr) >=
16252ffc8bcaSDan McDonald MAX_LOGICAL_DRIVES) || !instance->fast_path_io) {
1626ff38cf9dSAndy Fiddaman dev_err(instance->dip, CE_NOTE,
1627ff38cf9dSAndy Fiddaman "Fast Path NOT Possible, "
16282ffc8bcaSDan McDonald "targetId >= MAX_LOGICAL_DRIVES || "
16292ffc8bcaSDan McDonald "!instance->fast_path_io");
16302ffc8bcaSDan McDonald fp_possible = 0;
16312ffc8bcaSDan McDonald /* Set Regionlock flags to BYPASS */
16322ffc8bcaSDan McDonald /* io_request->RaidContext.regLockFlags = 0; */
16332ffc8bcaSDan McDonald ddi_put8(acc_handle,
16342ffc8bcaSDan McDonald &scsi_raid_io->RaidContext.regLockFlags, 0);
16352ffc8bcaSDan McDonald } else {
16362ffc8bcaSDan McDonald if (MR_BuildRaidContext(instance, &io_info,
16372ffc8bcaSDan McDonald &scsi_raid_io->RaidContext, local_map_ptr))
16382ffc8bcaSDan McDonald fp_possible = io_info.fpOkForIo;
16392ffc8bcaSDan McDonald }
16402ffc8bcaSDan McDonald
16412ffc8bcaSDan McDonald if (!enable_fp)
16422ffc8bcaSDan McDonald fp_possible = 0;
16432ffc8bcaSDan McDonald
16442ffc8bcaSDan McDonald con_log(CL_ANN1, (CE_NOTE, "enable_fp %d "
16452ffc8bcaSDan McDonald "instance->fast_path_io %d fp_possible %d",
16462ffc8bcaSDan McDonald enable_fp, instance->fast_path_io, fp_possible));
16472ffc8bcaSDan McDonald
16482ffc8bcaSDan McDonald if (fp_possible) {
16492ffc8bcaSDan McDonald
16502ffc8bcaSDan McDonald /* Check for DIF enabled LD */
16512ffc8bcaSDan McDonald if (MR_CheckDIF(acmd->device_id, local_map_ptr)) {
16522ffc8bcaSDan McDonald /* Prepare 32 Byte CDB for DIF capable Disk */
16532ffc8bcaSDan McDonald mrsas_tbolt_prepare_cdb(instance,
16542ffc8bcaSDan McDonald scsi_raid_io->CDB.CDB32,
16552ffc8bcaSDan McDonald &io_info, scsi_raid_io, start_lba_lo);
16562ffc8bcaSDan McDonald } else {
16572ffc8bcaSDan McDonald mrsas_tbolt_set_pd_lba(scsi_raid_io->CDB.CDB32,
16583344ffb7SToomas Soome sizeof (scsi_raid_io->CDB.CDB32),
16592ffc8bcaSDan McDonald (uint8_t *)&pd_cmd_cdblen,
16602ffc8bcaSDan McDonald io_info.pdBlock, io_info.numBlocks);
16612ffc8bcaSDan McDonald ddi_put16(acc_handle,
16622ffc8bcaSDan McDonald &scsi_raid_io->IoFlags, pd_cmd_cdblen);
16632ffc8bcaSDan McDonald }
16642ffc8bcaSDan McDonald
16652ffc8bcaSDan McDonald ddi_put8(acc_handle, &scsi_raid_io->Function,
16662ffc8bcaSDan McDonald MPI2_FUNCTION_SCSI_IO_REQUEST);
16672ffc8bcaSDan McDonald
16682ffc8bcaSDan McDonald ReqDescUnion->SCSIIO.RequestFlags =
16692ffc8bcaSDan McDonald (MPI2_REQ_DESCRIPT_FLAGS_HIGH_PRIORITY <<
16702ffc8bcaSDan McDonald MPI2_REQ_DESCRIPT_FLAGS_TYPE_SHIFT);
16712ffc8bcaSDan McDonald
1672df950592SHummyPkg if (instance->gen3) {
16732ffc8bcaSDan McDonald uint8_t regLockFlags = ddi_get8(acc_handle,
16742ffc8bcaSDan McDonald &scsi_raid_io->RaidContext.regLockFlags);
16752ffc8bcaSDan McDonald uint16_t IoFlags = ddi_get16(acc_handle,
16762ffc8bcaSDan McDonald &scsi_raid_io->IoFlags);
16772ffc8bcaSDan McDonald
16782ffc8bcaSDan McDonald if (regLockFlags == REGION_TYPE_UNUSED)
16792ffc8bcaSDan McDonald ReqDescUnion->SCSIIO.RequestFlags =
16802ffc8bcaSDan McDonald (MPI2_REQ_DESCRIPT_FLAGS_NO_LOCK <<
16812ffc8bcaSDan McDonald MPI2_REQ_DESCRIPT_FLAGS_TYPE_SHIFT);
16822ffc8bcaSDan McDonald
16832ffc8bcaSDan McDonald IoFlags |=
16842ffc8bcaSDan McDonald MPI25_SAS_DEVICE0_FLAGS_ENABLED_FAST_PATH;
16852ffc8bcaSDan McDonald regLockFlags |=
16862ffc8bcaSDan McDonald (MR_RL_FLAGS_GRANT_DESTINATION_CUDA |
16872ffc8bcaSDan McDonald MR_RL_FLAGS_SEQ_NUM_ENABLE);
16882ffc8bcaSDan McDonald
16892ffc8bcaSDan McDonald ddi_put8(acc_handle,
16902ffc8bcaSDan McDonald &scsi_raid_io->ChainOffset, 0);
16912ffc8bcaSDan McDonald ddi_put8(acc_handle,
16922ffc8bcaSDan McDonald &scsi_raid_io->RaidContext.nsegType,
16932ffc8bcaSDan McDonald ((0x01 << MPI2_NSEG_FLAGS_SHIFT) |
16942ffc8bcaSDan McDonald MPI2_TYPE_CUDA));
16952ffc8bcaSDan McDonald ddi_put8(acc_handle,
16962ffc8bcaSDan McDonald &scsi_raid_io->RaidContext.regLockFlags,
16972ffc8bcaSDan McDonald regLockFlags);
16982ffc8bcaSDan McDonald ddi_put16(acc_handle,
16992ffc8bcaSDan McDonald &scsi_raid_io->IoFlags, IoFlags);
17002ffc8bcaSDan McDonald }
17012ffc8bcaSDan McDonald
17022ffc8bcaSDan McDonald if ((instance->load_balance_info[
17032ffc8bcaSDan McDonald acmd->device_id].loadBalanceFlag) &&
17042ffc8bcaSDan McDonald (io_info.isRead)) {
17052ffc8bcaSDan McDonald io_info.devHandle =
17062ffc8bcaSDan McDonald get_updated_dev_handle(&instance->
17072ffc8bcaSDan McDonald load_balance_info[acmd->device_id],
17082ffc8bcaSDan McDonald &io_info);
17092ffc8bcaSDan McDonald cmd->load_balance_flag |=
17102ffc8bcaSDan McDonald MEGASAS_LOAD_BALANCE_FLAG;
17112ffc8bcaSDan McDonald } else {
17122ffc8bcaSDan McDonald cmd->load_balance_flag &=
17132ffc8bcaSDan McDonald ~MEGASAS_LOAD_BALANCE_FLAG;
17142ffc8bcaSDan McDonald }
17152ffc8bcaSDan McDonald
17162ffc8bcaSDan McDonald ReqDescUnion->SCSIIO.DevHandle = io_info.devHandle;
17172ffc8bcaSDan McDonald ddi_put16(acc_handle, &scsi_raid_io->DevHandle,
17182ffc8bcaSDan McDonald io_info.devHandle);
17192ffc8bcaSDan McDonald
1720e65bc174SAndy Fiddaman } else { /* FP Not Possible */
1721e65bc174SAndy Fiddaman
17222ffc8bcaSDan McDonald ddi_put8(acc_handle, &scsi_raid_io->Function,
17232ffc8bcaSDan McDonald MPI2_FUNCTION_LD_IO_REQUEST);
17242ffc8bcaSDan McDonald
17252ffc8bcaSDan McDonald ddi_put16(acc_handle,
17262ffc8bcaSDan McDonald &scsi_raid_io->DevHandle, acmd->device_id);
17272ffc8bcaSDan McDonald
17282ffc8bcaSDan McDonald ReqDescUnion->SCSIIO.RequestFlags =
17292ffc8bcaSDan McDonald (MPI2_REQ_DESCRIPT_FLAGS_LD_IO <<
17302ffc8bcaSDan McDonald MPI2_REQ_DESCRIPT_FLAGS_TYPE_SHIFT);
17312ffc8bcaSDan McDonald
17322ffc8bcaSDan McDonald ddi_put16(acc_handle,
17332ffc8bcaSDan McDonald &scsi_raid_io->RaidContext.timeoutValue,
17342ffc8bcaSDan McDonald local_map_ptr->raidMap.fpPdIoTimeoutSec);
17352ffc8bcaSDan McDonald
1736df950592SHummyPkg if (instance->gen3) {
17372ffc8bcaSDan McDonald uint8_t regLockFlags = ddi_get8(acc_handle,
17382ffc8bcaSDan McDonald &scsi_raid_io->RaidContext.regLockFlags);
17392ffc8bcaSDan McDonald
17402ffc8bcaSDan McDonald if (regLockFlags == REGION_TYPE_UNUSED) {
17412ffc8bcaSDan McDonald ReqDescUnion->SCSIIO.RequestFlags =
17422ffc8bcaSDan McDonald (MPI2_REQ_DESCRIPT_FLAGS_NO_LOCK <<
17432ffc8bcaSDan McDonald MPI2_REQ_DESCRIPT_FLAGS_TYPE_SHIFT);
17442ffc8bcaSDan McDonald }
17452ffc8bcaSDan McDonald
17462ffc8bcaSDan McDonald regLockFlags |=
17472ffc8bcaSDan McDonald (MR_RL_FLAGS_GRANT_DESTINATION_CPU0 |
17482ffc8bcaSDan McDonald MR_RL_FLAGS_SEQ_NUM_ENABLE);
17492ffc8bcaSDan McDonald
17502ffc8bcaSDan McDonald ddi_put8(acc_handle,
17512ffc8bcaSDan McDonald &scsi_raid_io->RaidContext.nsegType,
17522ffc8bcaSDan McDonald ((0x01 << MPI2_NSEG_FLAGS_SHIFT) |
17532ffc8bcaSDan McDonald MPI2_TYPE_CUDA));
17542ffc8bcaSDan McDonald ddi_put8(acc_handle,
17552ffc8bcaSDan McDonald &scsi_raid_io->RaidContext.regLockFlags,
17562ffc8bcaSDan McDonald regLockFlags);
17572ffc8bcaSDan McDonald }
17582ffc8bcaSDan McDonald } /* Not FP */
17592ffc8bcaSDan McDonald
17602ffc8bcaSDan McDonald /* Release SYNC MAP UPDATE lock */
17612ffc8bcaSDan McDonald mutex_exit(&instance->sync_map_mtx);
17622ffc8bcaSDan McDonald
17632ffc8bcaSDan McDonald break;
1764e65bc174SAndy Fiddaman
17652ffc8bcaSDan McDonald case 0x35: { /* SCMD_SYNCHRONIZE_CACHE */
17662ffc8bcaSDan McDonald return_raid_msg_pkt(instance, cmd);
17672ffc8bcaSDan McDonald *cmd_done = 1;
17682ffc8bcaSDan McDonald return (NULL);
17692ffc8bcaSDan McDonald }
17702ffc8bcaSDan McDonald
17712ffc8bcaSDan McDonald case SCMD_MODE_SENSE:
17722ffc8bcaSDan McDonald case SCMD_MODE_SENSE_G1: {
17732ffc8bcaSDan McDonald union scsi_cdb *cdbp;
17742ffc8bcaSDan McDonald uint16_t page_code;
17752ffc8bcaSDan McDonald
17762ffc8bcaSDan McDonald cdbp = (void *)pkt->pkt_cdbp;
17772ffc8bcaSDan McDonald page_code = (uint16_t)cdbp->cdb_un.sg.scsi[0];
17782ffc8bcaSDan McDonald switch (page_code) {
17792ffc8bcaSDan McDonald case 0x3:
17802ffc8bcaSDan McDonald case 0x4:
17812ffc8bcaSDan McDonald (void) mrsas_mode_sense_build(pkt);
17822ffc8bcaSDan McDonald return_raid_msg_pkt(instance, cmd);
17832ffc8bcaSDan McDonald *cmd_done = 1;
17842ffc8bcaSDan McDonald return (NULL);
17852ffc8bcaSDan McDonald }
1786e65bc174SAndy Fiddaman return (cmd);
17872ffc8bcaSDan McDonald }
17882ffc8bcaSDan McDonald
1789e65bc174SAndy Fiddaman default:
1790e65bc174SAndy Fiddaman /* Pass-through command to logical drive */
1791e65bc174SAndy Fiddaman ddi_put8(acc_handle, &scsi_raid_io->Function,
1792e65bc174SAndy Fiddaman MPI2_FUNCTION_LD_IO_REQUEST);
1793e65bc174SAndy Fiddaman ddi_put8(acc_handle, &scsi_raid_io->LUN[1], acmd->lun);
1794e65bc174SAndy Fiddaman ddi_put16(acc_handle, &scsi_raid_io->DevHandle,
1795e65bc174SAndy Fiddaman acmd->device_id);
1796e65bc174SAndy Fiddaman ReqDescUnion->SCSIIO.RequestFlags =
1797e65bc174SAndy Fiddaman (MPI2_REQ_DESCRIPT_FLAGS_SCSI_IO <<
1798e65bc174SAndy Fiddaman MPI2_REQ_DESCRIPT_FLAGS_TYPE_SHIFT);
1799e65bc174SAndy Fiddaman break;
1800e65bc174SAndy Fiddaman }
1801e65bc174SAndy Fiddaman } else { /* Physical */
1802e65bc174SAndy Fiddaman /* Pass-through command to physical drive */
18032ffc8bcaSDan McDonald
18042ffc8bcaSDan McDonald /* Acquire SYNC MAP UPDATE lock */
18052ffc8bcaSDan McDonald mutex_enter(&instance->sync_map_mtx);
18062ffc8bcaSDan McDonald
1807e65bc174SAndy Fiddaman local_map_ptr = instance->ld_map[instance->map_id & 1];
18082ffc8bcaSDan McDonald
18092ffc8bcaSDan McDonald ddi_put8(acc_handle, &scsi_raid_io->Function,
18102ffc8bcaSDan McDonald MPI2_FUNCTION_SCSI_IO_REQUEST);
18112ffc8bcaSDan McDonald
18122ffc8bcaSDan McDonald ReqDescUnion->SCSIIO.RequestFlags =
18132ffc8bcaSDan McDonald (MPI2_REQ_DESCRIPT_FLAGS_HIGH_PRIORITY <<
18142ffc8bcaSDan McDonald MPI2_REQ_DESCRIPT_FLAGS_TYPE_SHIFT);
18152ffc8bcaSDan McDonald
18162ffc8bcaSDan McDonald ddi_put16(acc_handle, &scsi_raid_io->DevHandle,
18172ffc8bcaSDan McDonald local_map_ptr->raidMap.
18182ffc8bcaSDan McDonald devHndlInfo[acmd->device_id].curDevHdl);
18192ffc8bcaSDan McDonald
18202ffc8bcaSDan McDonald /* Set regLockFlasgs to REGION_TYPE_BYPASS */
18212ffc8bcaSDan McDonald ddi_put8(acc_handle,
18222ffc8bcaSDan McDonald &scsi_raid_io->RaidContext.regLockFlags, 0);
18232ffc8bcaSDan McDonald ddi_put64(acc_handle,
1824e65bc174SAndy Fiddaman &scsi_raid_io->RaidContext.regLockRowLBA, 0);
18252ffc8bcaSDan McDonald ddi_put32(acc_handle,
1826e65bc174SAndy Fiddaman &scsi_raid_io->RaidContext.regLockLength, 0);
18272ffc8bcaSDan McDonald ddi_put8(acc_handle,
18282ffc8bcaSDan McDonald &scsi_raid_io->RaidContext.RAIDFlags,
18292ffc8bcaSDan McDonald MR_RAID_FLAGS_IO_SUB_TYPE_SYSTEM_PD <<
18302ffc8bcaSDan McDonald MR_RAID_CTX_RAID_FLAGS_IO_SUB_TYPE_SHIFT);
18312ffc8bcaSDan McDonald ddi_put16(acc_handle,
18322ffc8bcaSDan McDonald &scsi_raid_io->RaidContext.timeoutValue,
18332ffc8bcaSDan McDonald local_map_ptr->raidMap.fpPdIoTimeoutSec);
18342ffc8bcaSDan McDonald ddi_put16(acc_handle,
18352ffc8bcaSDan McDonald &scsi_raid_io->RaidContext.ldTargetId,
18362ffc8bcaSDan McDonald acmd->device_id);
18372ffc8bcaSDan McDonald ddi_put8(acc_handle,
18382ffc8bcaSDan McDonald &scsi_raid_io->LUN[1], acmd->lun);
18392ffc8bcaSDan McDonald
1840df950592SHummyPkg if (instance->fast_path_io && instance->gen3) {
1841e65bc174SAndy Fiddaman uint16_t IoFlags = ddi_get16(acc_handle,
1842e65bc174SAndy Fiddaman &scsi_raid_io->IoFlags);
1843e65bc174SAndy Fiddaman IoFlags |= MPI25_SAS_DEVICE0_FLAGS_ENABLED_FAST_PATH;
1844e65bc174SAndy Fiddaman ddi_put16(acc_handle, &scsi_raid_io->IoFlags, IoFlags);
1845e65bc174SAndy Fiddaman }
1846e65bc174SAndy Fiddaman ddi_put16(acc_handle, &ReqDescUnion->SCSIIO.DevHandle,
1847e65bc174SAndy Fiddaman local_map_ptr->raidMap.
1848e65bc174SAndy Fiddaman devHndlInfo[acmd->device_id].curDevHdl);
1849e65bc174SAndy Fiddaman
18502ffc8bcaSDan McDonald /* Release SYNC MAP UPDATE lock */
18512ffc8bcaSDan McDonald mutex_exit(&instance->sync_map_mtx);
18522ffc8bcaSDan McDonald }
18532ffc8bcaSDan McDonald
1854e65bc174SAndy Fiddaman /* Set sense buffer physical address/length in scsi_io_request. */
1855e65bc174SAndy Fiddaman ddi_put32(acc_handle, &scsi_raid_io->SenseBufferLowAddress,
18562ffc8bcaSDan McDonald cmd->sense_phys_addr1);
1857e65bc174SAndy Fiddaman ddi_put8(acc_handle, &scsi_raid_io->SenseBufferLength, SENSE_LENGTH);
18582ffc8bcaSDan McDonald
18592ffc8bcaSDan McDonald /* Construct SGL */
18602ffc8bcaSDan McDonald ddi_put8(acc_handle, &scsi_raid_io->SGLOffset0,
18612ffc8bcaSDan McDonald offsetof(MPI2_RAID_SCSI_IO_REQUEST, SGL) / 4);
18622ffc8bcaSDan McDonald
18632ffc8bcaSDan McDonald (void) mr_sas_tbolt_build_sgl(instance, acmd, cmd,
18642ffc8bcaSDan McDonald scsi_raid_io, &datalen);
18652ffc8bcaSDan McDonald
1866e65bc174SAndy Fiddaman ddi_put32(acc_handle, &scsi_raid_io->DataLength, datalen);
18672ffc8bcaSDan McDonald
18682ffc8bcaSDan McDonald con_log(CL_ANN, (CE_CONT,
18692ffc8bcaSDan McDonald "tbolt_build_cmd CDB[0] =%x, TargetID =%x\n",
18702ffc8bcaSDan McDonald pkt->pkt_cdbp[0], acmd->device_id));
18712ffc8bcaSDan McDonald con_log(CL_DLEVEL1, (CE_CONT,
18722ffc8bcaSDan McDonald "data length = %x\n",
18732ffc8bcaSDan McDonald scsi_raid_io->DataLength));
18742ffc8bcaSDan McDonald con_log(CL_DLEVEL1, (CE_CONT,
18752ffc8bcaSDan McDonald "cdb length = %x\n",
18762ffc8bcaSDan McDonald acmd->cmd_cdblen));
18772ffc8bcaSDan McDonald
18782ffc8bcaSDan McDonald return (cmd);
18792ffc8bcaSDan McDonald }
18802ffc8bcaSDan McDonald
18812ffc8bcaSDan McDonald uint32_t
tbolt_read_fw_status_reg(struct mrsas_instance * instance)18822ffc8bcaSDan McDonald tbolt_read_fw_status_reg(struct mrsas_instance *instance)
18832ffc8bcaSDan McDonald {
18842ffc8bcaSDan McDonald return ((uint32_t)RD_OB_SCRATCH_PAD_0(instance));
18852ffc8bcaSDan McDonald }
18862ffc8bcaSDan McDonald
18872ffc8bcaSDan McDonald void
tbolt_issue_cmd(struct mrsas_cmd * cmd,struct mrsas_instance * instance)18882ffc8bcaSDan McDonald tbolt_issue_cmd(struct mrsas_cmd *cmd, struct mrsas_instance *instance)
18892ffc8bcaSDan McDonald {
18902ffc8bcaSDan McDonald MRSAS_REQUEST_DESCRIPTOR_UNION *req_desc = cmd->request_desc;
18911a5e258fSJosef 'Jeff' Sipek atomic_inc_16(&instance->fw_outstanding);
18922ffc8bcaSDan McDonald
18932ffc8bcaSDan McDonald struct scsi_pkt *pkt;
18942ffc8bcaSDan McDonald
18952ffc8bcaSDan McDonald con_log(CL_ANN1,
18962ffc8bcaSDan McDonald (CE_NOTE, "tbolt_issue_cmd: cmd->[SMID]=0x%X", cmd->SMID));
18972ffc8bcaSDan McDonald
18982ffc8bcaSDan McDonald con_log(CL_DLEVEL1, (CE_CONT,
18992ffc8bcaSDan McDonald " [req desc Words] %" PRIx64 " \n", req_desc->Words));
19002ffc8bcaSDan McDonald con_log(CL_DLEVEL1, (CE_CONT,
19012ffc8bcaSDan McDonald " [req desc low part] %x \n",
19022ffc8bcaSDan McDonald (uint_t)(req_desc->Words & 0xffffffffff)));
19032ffc8bcaSDan McDonald con_log(CL_DLEVEL1, (CE_CONT,
19042ffc8bcaSDan McDonald " [req desc high part] %x \n", (uint_t)(req_desc->Words >> 32)));
19052ffc8bcaSDan McDonald pkt = cmd->pkt;
19062ffc8bcaSDan McDonald
19072ffc8bcaSDan McDonald if (pkt) {
19082ffc8bcaSDan McDonald con_log(CL_ANN1, (CE_CONT, "%llx :TBOLT issue_cmd_ppc:"
19092ffc8bcaSDan McDonald "ISSUED CMD TO FW : called : cmd:"
19102ffc8bcaSDan McDonald ": %p instance : %p pkt : %p pkt_time : %x\n",
19112ffc8bcaSDan McDonald gethrtime(), (void *)cmd, (void *)instance,
19122ffc8bcaSDan McDonald (void *)pkt, cmd->drv_pkt_time));
19132ffc8bcaSDan McDonald if (instance->adapterresetinprogress) {
19142ffc8bcaSDan McDonald cmd->drv_pkt_time = (uint16_t)debug_timeout_g;
19152ffc8bcaSDan McDonald con_log(CL_ANN, (CE_NOTE,
19162ffc8bcaSDan McDonald "TBOLT Reset the scsi_pkt timer"));
19172ffc8bcaSDan McDonald } else {
19182ffc8bcaSDan McDonald push_pending_mfi_pkt(instance, cmd);
19192ffc8bcaSDan McDonald }
19202ffc8bcaSDan McDonald
19212ffc8bcaSDan McDonald } else {
19222ffc8bcaSDan McDonald con_log(CL_ANN1, (CE_CONT, "%llx :TBOLT issue_cmd_ppc:"
19232ffc8bcaSDan McDonald "ISSUED CMD TO FW : called : cmd : %p, instance: %p"
19242ffc8bcaSDan McDonald "(NO PKT)\n", gethrtime(), (void *)cmd, (void *)instance));
19252ffc8bcaSDan McDonald }
19262ffc8bcaSDan McDonald
19272ffc8bcaSDan McDonald /* Issue the command to the FW */
19282ffc8bcaSDan McDonald mutex_enter(&instance->reg_write_mtx);
19292ffc8bcaSDan McDonald WR_IB_LOW_QPORT((uint32_t)(req_desc->Words), instance);
19302ffc8bcaSDan McDonald WR_IB_HIGH_QPORT((uint32_t)(req_desc->Words >> 32), instance);
19312ffc8bcaSDan McDonald mutex_exit(&instance->reg_write_mtx);
19322ffc8bcaSDan McDonald }
19332ffc8bcaSDan McDonald
19342ffc8bcaSDan McDonald /*
19352ffc8bcaSDan McDonald * issue_cmd_in_sync_mode
19362ffc8bcaSDan McDonald */
19372ffc8bcaSDan McDonald int
tbolt_issue_cmd_in_sync_mode(struct mrsas_instance * instance,struct mrsas_cmd * cmd)19382ffc8bcaSDan McDonald tbolt_issue_cmd_in_sync_mode(struct mrsas_instance *instance,
19392ffc8bcaSDan McDonald struct mrsas_cmd *cmd)
19402ffc8bcaSDan McDonald {
19412ffc8bcaSDan McDonald int i;
19422ffc8bcaSDan McDonald uint32_t msecs = MFI_POLL_TIMEOUT_SECS * MILLISEC;
19432ffc8bcaSDan McDonald MRSAS_REQUEST_DESCRIPTOR_UNION *req_desc = cmd->request_desc;
19442ffc8bcaSDan McDonald
19452ffc8bcaSDan McDonald struct mrsas_header *hdr;
19462ffc8bcaSDan McDonald hdr = (struct mrsas_header *)&cmd->frame->hdr;
19472ffc8bcaSDan McDonald
19482ffc8bcaSDan McDonald con_log(CL_ANN,
19492ffc8bcaSDan McDonald (CE_NOTE, "tbolt_issue_cmd_in_sync_mode: cmd->[SMID]=0x%X",
19502ffc8bcaSDan McDonald cmd->SMID));
19512ffc8bcaSDan McDonald
19522ffc8bcaSDan McDonald
19532ffc8bcaSDan McDonald if (instance->adapterresetinprogress) {
19542ffc8bcaSDan McDonald cmd->drv_pkt_time = ddi_get16
19552ffc8bcaSDan McDonald (cmd->frame_dma_obj.acc_handle, &hdr->timeout);
19562ffc8bcaSDan McDonald if (cmd->drv_pkt_time < debug_timeout_g)
19572ffc8bcaSDan McDonald cmd->drv_pkt_time = (uint16_t)debug_timeout_g;
19582ffc8bcaSDan McDonald con_log(CL_ANN, (CE_NOTE, "tbolt_issue_cmd_in_sync_mode:"
19592ffc8bcaSDan McDonald "RESET-IN-PROGRESS, issue cmd & return."));
19602ffc8bcaSDan McDonald
19612ffc8bcaSDan McDonald mutex_enter(&instance->reg_write_mtx);
19622ffc8bcaSDan McDonald WR_IB_LOW_QPORT((uint32_t)(req_desc->Words), instance);
19632ffc8bcaSDan McDonald WR_IB_HIGH_QPORT((uint32_t)(req_desc->Words >> 32), instance);
19642ffc8bcaSDan McDonald mutex_exit(&instance->reg_write_mtx);
19652ffc8bcaSDan McDonald
19662ffc8bcaSDan McDonald return (DDI_SUCCESS);
19672ffc8bcaSDan McDonald } else {
19682ffc8bcaSDan McDonald con_log(CL_ANN1, (CE_NOTE,
19692ffc8bcaSDan McDonald "tbolt_issue_cmd_in_sync_mode: pushing the pkt"));
19702ffc8bcaSDan McDonald push_pending_mfi_pkt(instance, cmd);
19712ffc8bcaSDan McDonald }
19722ffc8bcaSDan McDonald
19732ffc8bcaSDan McDonald con_log(CL_DLEVEL2, (CE_NOTE,
19742ffc8bcaSDan McDonald "HighQport offset :%p",
19752ffc8bcaSDan McDonald (void *)((uintptr_t)(instance)->regmap + IB_HIGH_QPORT)));
19762ffc8bcaSDan McDonald con_log(CL_DLEVEL2, (CE_NOTE,
19772ffc8bcaSDan McDonald "LowQport offset :%p",
19782ffc8bcaSDan McDonald (void *)((uintptr_t)(instance)->regmap + IB_LOW_QPORT)));
19792ffc8bcaSDan McDonald
19802ffc8bcaSDan McDonald cmd->sync_cmd = MRSAS_TRUE;
19812ffc8bcaSDan McDonald cmd->cmd_status = ENODATA;
19822ffc8bcaSDan McDonald
19832ffc8bcaSDan McDonald
19842ffc8bcaSDan McDonald mutex_enter(&instance->reg_write_mtx);
19852ffc8bcaSDan McDonald WR_IB_LOW_QPORT((uint32_t)(req_desc->Words), instance);
19862ffc8bcaSDan McDonald WR_IB_HIGH_QPORT((uint32_t)(req_desc->Words >> 32), instance);
19872ffc8bcaSDan McDonald mutex_exit(&instance->reg_write_mtx);
19882ffc8bcaSDan McDonald
19892ffc8bcaSDan McDonald con_log(CL_ANN1, (CE_NOTE,
19902ffc8bcaSDan McDonald " req desc high part %x", (uint_t)(req_desc->Words >> 32)));
19912ffc8bcaSDan McDonald con_log(CL_ANN1, (CE_NOTE, " req desc low part %x",
19922ffc8bcaSDan McDonald (uint_t)(req_desc->Words & 0xffffffff)));
19932ffc8bcaSDan McDonald
19942ffc8bcaSDan McDonald mutex_enter(&instance->int_cmd_mtx);
19952ffc8bcaSDan McDonald for (i = 0; i < msecs && (cmd->cmd_status == ENODATA); i++) {
19962ffc8bcaSDan McDonald cv_wait(&instance->int_cmd_cv, &instance->int_cmd_mtx);
19972ffc8bcaSDan McDonald }
19982ffc8bcaSDan McDonald mutex_exit(&instance->int_cmd_mtx);
19992ffc8bcaSDan McDonald
20002ffc8bcaSDan McDonald
20012ffc8bcaSDan McDonald if (i < (msecs -1)) {
20022ffc8bcaSDan McDonald return (DDI_SUCCESS);
20032ffc8bcaSDan McDonald } else {
20042ffc8bcaSDan McDonald return (DDI_FAILURE);
20052ffc8bcaSDan McDonald }
20062ffc8bcaSDan McDonald }
20072ffc8bcaSDan McDonald
20082ffc8bcaSDan McDonald /*
20092ffc8bcaSDan McDonald * issue_cmd_in_poll_mode
20102ffc8bcaSDan McDonald */
20112ffc8bcaSDan McDonald int
tbolt_issue_cmd_in_poll_mode(struct mrsas_instance * instance,struct mrsas_cmd * cmd)20122ffc8bcaSDan McDonald tbolt_issue_cmd_in_poll_mode(struct mrsas_instance *instance,
20132ffc8bcaSDan McDonald struct mrsas_cmd *cmd)
20142ffc8bcaSDan McDonald {
20152ffc8bcaSDan McDonald int i;
20162ffc8bcaSDan McDonald uint16_t flags;
20172ffc8bcaSDan McDonald uint32_t msecs = MFI_POLL_TIMEOUT_SECS * MILLISEC;
20182ffc8bcaSDan McDonald struct mrsas_header *frame_hdr;
20192ffc8bcaSDan McDonald
20202ffc8bcaSDan McDonald con_log(CL_ANN,
20212ffc8bcaSDan McDonald (CE_NOTE, "tbolt_issue_cmd_in_poll_mode: cmd->[SMID]=0x%X",
20222ffc8bcaSDan McDonald cmd->SMID));
20232ffc8bcaSDan McDonald
20242ffc8bcaSDan McDonald MRSAS_REQUEST_DESCRIPTOR_UNION *req_desc = cmd->request_desc;
20252ffc8bcaSDan McDonald
20262ffc8bcaSDan McDonald frame_hdr = (struct mrsas_header *)&cmd->frame->hdr;
20272ffc8bcaSDan McDonald ddi_put8(cmd->frame_dma_obj.acc_handle, &frame_hdr->cmd_status,
20282ffc8bcaSDan McDonald MFI_CMD_STATUS_POLL_MODE);
20292ffc8bcaSDan McDonald flags = ddi_get16(cmd->frame_dma_obj.acc_handle, &frame_hdr->flags);
20302ffc8bcaSDan McDonald flags |= MFI_FRAME_DONT_POST_IN_REPLY_QUEUE;
20312ffc8bcaSDan McDonald ddi_put16(cmd->frame_dma_obj.acc_handle, &frame_hdr->flags, flags);
20322ffc8bcaSDan McDonald
20332ffc8bcaSDan McDonald con_log(CL_ANN1, (CE_NOTE, " req desc low part %x",
20342ffc8bcaSDan McDonald (uint_t)(req_desc->Words & 0xffffffff)));
20352ffc8bcaSDan McDonald con_log(CL_ANN1, (CE_NOTE,
20362ffc8bcaSDan McDonald " req desc high part %x", (uint_t)(req_desc->Words >> 32)));
20372ffc8bcaSDan McDonald
20382ffc8bcaSDan McDonald /* issue the frame using inbound queue port */
20392ffc8bcaSDan McDonald mutex_enter(&instance->reg_write_mtx);
20402ffc8bcaSDan McDonald WR_IB_LOW_QPORT((uint32_t)(req_desc->Words), instance);
20412ffc8bcaSDan McDonald WR_IB_HIGH_QPORT((uint32_t)(req_desc->Words >> 32), instance);
20422ffc8bcaSDan McDonald mutex_exit(&instance->reg_write_mtx);
20432ffc8bcaSDan McDonald
20442ffc8bcaSDan McDonald for (i = 0; i < msecs && (
20452ffc8bcaSDan McDonald ddi_get8(cmd->frame_dma_obj.acc_handle, &frame_hdr->cmd_status)
20462ffc8bcaSDan McDonald == MFI_CMD_STATUS_POLL_MODE); i++) {
20472ffc8bcaSDan McDonald /* wait for cmd_status to change from 0xFF */
20482ffc8bcaSDan McDonald drv_usecwait(MILLISEC); /* wait for 1000 usecs */
20492ffc8bcaSDan McDonald }
20502ffc8bcaSDan McDonald
20514bc492d2SAndy Fiddaman DTRACE_PROBE1(tbolt_complete_poll_cmd, uint8_t, i);
20524bc492d2SAndy Fiddaman
20532ffc8bcaSDan McDonald if (ddi_get8(cmd->frame_dma_obj.acc_handle,
20542ffc8bcaSDan McDonald &frame_hdr->cmd_status) == MFI_CMD_STATUS_POLL_MODE) {
20552ffc8bcaSDan McDonald con_log(CL_ANN1, (CE_NOTE,
20562ffc8bcaSDan McDonald " cmd failed %" PRIx64, (req_desc->Words)));
20572ffc8bcaSDan McDonald return (DDI_FAILURE);
20582ffc8bcaSDan McDonald }
20592ffc8bcaSDan McDonald
20602ffc8bcaSDan McDonald return (DDI_SUCCESS);
20612ffc8bcaSDan McDonald }
20622ffc8bcaSDan McDonald
20632ffc8bcaSDan McDonald void
tbolt_enable_intr(struct mrsas_instance * instance)20642ffc8bcaSDan McDonald tbolt_enable_intr(struct mrsas_instance *instance)
20652ffc8bcaSDan McDonald {
20662ffc8bcaSDan McDonald /* TODO: For Thunderbolt/Invader also clear intr on enable */
20672ffc8bcaSDan McDonald /* writel(~0, ®s->outbound_intr_status); */
20682ffc8bcaSDan McDonald /* readl(®s->outbound_intr_status); */
20692ffc8bcaSDan McDonald
20702ffc8bcaSDan McDonald WR_OB_INTR_MASK(~(MFI_FUSION_ENABLE_INTERRUPT_MASK), instance);
20712ffc8bcaSDan McDonald
20722ffc8bcaSDan McDonald /* dummy read to force PCI flush */
20732ffc8bcaSDan McDonald (void) RD_OB_INTR_MASK(instance);
20742ffc8bcaSDan McDonald
20752ffc8bcaSDan McDonald }
20762ffc8bcaSDan McDonald
20772ffc8bcaSDan McDonald void
tbolt_disable_intr(struct mrsas_instance * instance)20782ffc8bcaSDan McDonald tbolt_disable_intr(struct mrsas_instance *instance)
20792ffc8bcaSDan McDonald {
20802ffc8bcaSDan McDonald uint32_t mask = 0xFFFFFFFF;
20812ffc8bcaSDan McDonald
20822ffc8bcaSDan McDonald WR_OB_INTR_MASK(mask, instance);
20832ffc8bcaSDan McDonald
20842ffc8bcaSDan McDonald /* Dummy readl to force pci flush */
20852ffc8bcaSDan McDonald
20862ffc8bcaSDan McDonald (void) RD_OB_INTR_MASK(instance);
20872ffc8bcaSDan McDonald }
20882ffc8bcaSDan McDonald
20892ffc8bcaSDan McDonald
20902ffc8bcaSDan McDonald int
tbolt_intr_ack(struct mrsas_instance * instance)20912ffc8bcaSDan McDonald tbolt_intr_ack(struct mrsas_instance *instance)
20922ffc8bcaSDan McDonald {
20932ffc8bcaSDan McDonald uint32_t status;
20942ffc8bcaSDan McDonald
20952ffc8bcaSDan McDonald /* check if it is our interrupt */
20962ffc8bcaSDan McDonald status = RD_OB_INTR_STATUS(instance);
20972ffc8bcaSDan McDonald con_log(CL_ANN1, (CE_NOTE,
20982ffc8bcaSDan McDonald "chkpnt: Entered tbolt_intr_ack status = %d", status));
20992ffc8bcaSDan McDonald
21002ffc8bcaSDan McDonald if (!(status & MFI_FUSION_ENABLE_INTERRUPT_MASK)) {
21012ffc8bcaSDan McDonald return (DDI_INTR_UNCLAIMED);
21022ffc8bcaSDan McDonald }
21032ffc8bcaSDan McDonald
21042ffc8bcaSDan McDonald if (mrsas_check_acc_handle(instance->regmap_handle) != DDI_SUCCESS) {
21052ffc8bcaSDan McDonald ddi_fm_service_impact(instance->dip, DDI_SERVICE_LOST);
21062ffc8bcaSDan McDonald return (DDI_INTR_UNCLAIMED);
21072ffc8bcaSDan McDonald }
21082ffc8bcaSDan McDonald
21092ffc8bcaSDan McDonald if ((status & 1) || (status & MFI_FUSION_ENABLE_INTERRUPT_MASK)) {
21102ffc8bcaSDan McDonald /* clear the interrupt by writing back the same value */
21112ffc8bcaSDan McDonald WR_OB_INTR_STATUS(status, instance);
21122ffc8bcaSDan McDonald /* dummy READ */
21132ffc8bcaSDan McDonald (void) RD_OB_INTR_STATUS(instance);
21142ffc8bcaSDan McDonald }
21152ffc8bcaSDan McDonald return (DDI_INTR_CLAIMED);
21162ffc8bcaSDan McDonald }
21172ffc8bcaSDan McDonald
21182ffc8bcaSDan McDonald /*
21192ffc8bcaSDan McDonald * get_raid_msg_pkt : Get a command from the free pool
21202ffc8bcaSDan McDonald * After successful allocation, the caller of this routine
21212ffc8bcaSDan McDonald * must clear the frame buffer (memset to zero) before
21222ffc8bcaSDan McDonald * using the packet further.
21232ffc8bcaSDan McDonald *
21242ffc8bcaSDan McDonald * ***** Note *****
21252ffc8bcaSDan McDonald * After clearing the frame buffer the context id of the
21262ffc8bcaSDan McDonald * frame buffer SHOULD be restored back.
21272ffc8bcaSDan McDonald */
21282ffc8bcaSDan McDonald
21292ffc8bcaSDan McDonald struct mrsas_cmd *
get_raid_msg_pkt(struct mrsas_instance * instance)21302ffc8bcaSDan McDonald get_raid_msg_pkt(struct mrsas_instance *instance)
21312ffc8bcaSDan McDonald {
21322ffc8bcaSDan McDonald mlist_t *head = &instance->cmd_pool_list;
21332ffc8bcaSDan McDonald struct mrsas_cmd *cmd = NULL;
21342ffc8bcaSDan McDonald
21352ffc8bcaSDan McDonald mutex_enter(&instance->cmd_pool_mtx);
21362ffc8bcaSDan McDonald ASSERT(mutex_owned(&instance->cmd_pool_mtx));
21372ffc8bcaSDan McDonald
21382ffc8bcaSDan McDonald
21392ffc8bcaSDan McDonald if (!mlist_empty(head)) {
21402ffc8bcaSDan McDonald cmd = mlist_entry(head->next, struct mrsas_cmd, list);
21412ffc8bcaSDan McDonald mlist_del_init(head->next);
21422ffc8bcaSDan McDonald }
21432ffc8bcaSDan McDonald if (cmd != NULL) {
21442ffc8bcaSDan McDonald cmd->pkt = NULL;
21452ffc8bcaSDan McDonald cmd->retry_count_for_ocr = 0;
21462ffc8bcaSDan McDonald cmd->drv_pkt_time = 0;
21472ffc8bcaSDan McDonald }
21482ffc8bcaSDan McDonald mutex_exit(&instance->cmd_pool_mtx);
21492ffc8bcaSDan McDonald
21502ffc8bcaSDan McDonald if (cmd != NULL)
21512ffc8bcaSDan McDonald bzero(cmd->scsi_io_request,
21522ffc8bcaSDan McDonald sizeof (Mpi2RaidSCSIIORequest_t));
21532ffc8bcaSDan McDonald return (cmd);
21542ffc8bcaSDan McDonald }
21552ffc8bcaSDan McDonald
21562ffc8bcaSDan McDonald struct mrsas_cmd *
get_raid_msg_mfi_pkt(struct mrsas_instance * instance)21572ffc8bcaSDan McDonald get_raid_msg_mfi_pkt(struct mrsas_instance *instance)
21582ffc8bcaSDan McDonald {
21592ffc8bcaSDan McDonald mlist_t *head = &instance->cmd_app_pool_list;
21602ffc8bcaSDan McDonald struct mrsas_cmd *cmd = NULL;
21612ffc8bcaSDan McDonald
21622ffc8bcaSDan McDonald mutex_enter(&instance->cmd_app_pool_mtx);
21632ffc8bcaSDan McDonald ASSERT(mutex_owned(&instance->cmd_app_pool_mtx));
21642ffc8bcaSDan McDonald
21652ffc8bcaSDan McDonald if (!mlist_empty(head)) {
21662ffc8bcaSDan McDonald cmd = mlist_entry(head->next, struct mrsas_cmd, list);
21672ffc8bcaSDan McDonald mlist_del_init(head->next);
21682ffc8bcaSDan McDonald }
21692ffc8bcaSDan McDonald if (cmd != NULL) {
21702ffc8bcaSDan McDonald cmd->retry_count_for_ocr = 0;
21712ffc8bcaSDan McDonald cmd->drv_pkt_time = 0;
21722ffc8bcaSDan McDonald cmd->pkt = NULL;
21732ffc8bcaSDan McDonald cmd->request_desc = NULL;
21742ffc8bcaSDan McDonald
21752ffc8bcaSDan McDonald }
21762ffc8bcaSDan McDonald
21772ffc8bcaSDan McDonald mutex_exit(&instance->cmd_app_pool_mtx);
21782ffc8bcaSDan McDonald
21792ffc8bcaSDan McDonald if (cmd != NULL) {
21802ffc8bcaSDan McDonald bzero(cmd->scsi_io_request,
21812ffc8bcaSDan McDonald sizeof (Mpi2RaidSCSIIORequest_t));
21822ffc8bcaSDan McDonald }
21832ffc8bcaSDan McDonald
21842ffc8bcaSDan McDonald return (cmd);
21852ffc8bcaSDan McDonald }
21862ffc8bcaSDan McDonald
21872ffc8bcaSDan McDonald /*
21882ffc8bcaSDan McDonald * return_raid_msg_pkt : Return a cmd to free command pool
21892ffc8bcaSDan McDonald */
21902ffc8bcaSDan McDonald void
return_raid_msg_pkt(struct mrsas_instance * instance,struct mrsas_cmd * cmd)21912ffc8bcaSDan McDonald return_raid_msg_pkt(struct mrsas_instance *instance, struct mrsas_cmd *cmd)
21922ffc8bcaSDan McDonald {
21932ffc8bcaSDan McDonald mutex_enter(&instance->cmd_pool_mtx);
21942ffc8bcaSDan McDonald ASSERT(mutex_owned(&instance->cmd_pool_mtx));
21952ffc8bcaSDan McDonald
21962ffc8bcaSDan McDonald
21972ffc8bcaSDan McDonald mlist_add_tail(&cmd->list, &instance->cmd_pool_list);
21982ffc8bcaSDan McDonald
21992ffc8bcaSDan McDonald mutex_exit(&instance->cmd_pool_mtx);
22002ffc8bcaSDan McDonald }
22012ffc8bcaSDan McDonald
22022ffc8bcaSDan McDonald void
return_raid_msg_mfi_pkt(struct mrsas_instance * instance,struct mrsas_cmd * cmd)22032ffc8bcaSDan McDonald return_raid_msg_mfi_pkt(struct mrsas_instance *instance, struct mrsas_cmd *cmd)
22042ffc8bcaSDan McDonald {
22052ffc8bcaSDan McDonald mutex_enter(&instance->cmd_app_pool_mtx);
22062ffc8bcaSDan McDonald ASSERT(mutex_owned(&instance->cmd_app_pool_mtx));
22072ffc8bcaSDan McDonald
22082ffc8bcaSDan McDonald mlist_add_tail(&cmd->list, &instance->cmd_app_pool_list);
22092ffc8bcaSDan McDonald
22102ffc8bcaSDan McDonald mutex_exit(&instance->cmd_app_pool_mtx);
22112ffc8bcaSDan McDonald }
22122ffc8bcaSDan McDonald
22132ffc8bcaSDan McDonald
22142ffc8bcaSDan McDonald void
mr_sas_tbolt_build_mfi_cmd(struct mrsas_instance * instance,struct mrsas_cmd * cmd)22152ffc8bcaSDan McDonald mr_sas_tbolt_build_mfi_cmd(struct mrsas_instance *instance,
22162ffc8bcaSDan McDonald struct mrsas_cmd *cmd)
22172ffc8bcaSDan McDonald {
22182ffc8bcaSDan McDonald Mpi2RaidSCSIIORequest_t *scsi_raid_io;
22192ffc8bcaSDan McDonald Mpi25IeeeSgeChain64_t *scsi_raid_io_sgl_ieee;
22202ffc8bcaSDan McDonald MRSAS_REQUEST_DESCRIPTOR_UNION *ReqDescUnion;
22212ffc8bcaSDan McDonald uint32_t index;
22222ffc8bcaSDan McDonald ddi_acc_handle_t acc_handle =
22232ffc8bcaSDan McDonald instance->mpi2_frame_pool_dma_obj.acc_handle;
22242ffc8bcaSDan McDonald
22252ffc8bcaSDan McDonald if (!instance->tbolt) {
22262ffc8bcaSDan McDonald con_log(CL_ANN, (CE_NOTE, "Not MFA enabled."));
22272ffc8bcaSDan McDonald return;
22282ffc8bcaSDan McDonald }
22292ffc8bcaSDan McDonald
22302ffc8bcaSDan McDonald index = cmd->index;
22312ffc8bcaSDan McDonald
22322ffc8bcaSDan McDonald ReqDescUnion = mr_sas_get_request_descriptor(instance, index);
22332ffc8bcaSDan McDonald
22342ffc8bcaSDan McDonald if (!ReqDescUnion) {
22352ffc8bcaSDan McDonald con_log(CL_ANN1, (CE_NOTE, "[NULL REQDESC]"));
22362ffc8bcaSDan McDonald return;
22372ffc8bcaSDan McDonald }
22382ffc8bcaSDan McDonald
22392ffc8bcaSDan McDonald con_log(CL_ANN1, (CE_NOTE, "[SMID]%x", cmd->SMID));
22402ffc8bcaSDan McDonald
22412ffc8bcaSDan McDonald ReqDescUnion->Words = 0;
22422ffc8bcaSDan McDonald
22432ffc8bcaSDan McDonald ReqDescUnion->SCSIIO.RequestFlags =
22442ffc8bcaSDan McDonald (MPI2_REQ_DESCRIPT_FLAGS_SCSI_IO <<
22452ffc8bcaSDan McDonald MPI2_REQ_DESCRIPT_FLAGS_TYPE_SHIFT);
22462ffc8bcaSDan McDonald
22472ffc8bcaSDan McDonald ReqDescUnion->SCSIIO.SMID = cmd->SMID;
22482ffc8bcaSDan McDonald
22492ffc8bcaSDan McDonald cmd->request_desc = ReqDescUnion;
22502ffc8bcaSDan McDonald
22512ffc8bcaSDan McDonald /* get raid message frame pointer */
22522ffc8bcaSDan McDonald scsi_raid_io = (Mpi2RaidSCSIIORequest_t *)cmd->scsi_io_request;
22532ffc8bcaSDan McDonald
2254df950592SHummyPkg if (instance->gen3) {
22552ffc8bcaSDan McDonald Mpi25IeeeSgeChain64_t *sgl_ptr_end = (Mpi25IeeeSgeChain64_t *)
22562ffc8bcaSDan McDonald &scsi_raid_io->SGL.IeeeChain;
22572ffc8bcaSDan McDonald sgl_ptr_end += instance->max_sge_in_main_msg - 1;
22582ffc8bcaSDan McDonald ddi_put8(acc_handle, &sgl_ptr_end->Flags, 0);
22592ffc8bcaSDan McDonald }
22602ffc8bcaSDan McDonald
22612ffc8bcaSDan McDonald ddi_put8(acc_handle, &scsi_raid_io->Function,
22622ffc8bcaSDan McDonald MPI2_FUNCTION_PASSTHRU_IO_REQUEST);
22632ffc8bcaSDan McDonald
22642ffc8bcaSDan McDonald ddi_put8(acc_handle, &scsi_raid_io->SGLOffset0,
22652ffc8bcaSDan McDonald offsetof(MPI2_RAID_SCSI_IO_REQUEST, SGL) / 4);
22662ffc8bcaSDan McDonald
22672ffc8bcaSDan McDonald ddi_put8(acc_handle, &scsi_raid_io->ChainOffset,
22682ffc8bcaSDan McDonald (U8)offsetof(MPI2_RAID_SCSI_IO_REQUEST, SGL) / 16);
22692ffc8bcaSDan McDonald
22702ffc8bcaSDan McDonald ddi_put32(acc_handle, &scsi_raid_io->SenseBufferLowAddress,
22712ffc8bcaSDan McDonald cmd->sense_phys_addr1);
22722ffc8bcaSDan McDonald
22732ffc8bcaSDan McDonald
22742ffc8bcaSDan McDonald scsi_raid_io_sgl_ieee =
22752ffc8bcaSDan McDonald (Mpi25IeeeSgeChain64_t *)&scsi_raid_io->SGL.IeeeChain;
22762ffc8bcaSDan McDonald
22772ffc8bcaSDan McDonald ddi_put64(acc_handle, &scsi_raid_io_sgl_ieee->Address,
22782ffc8bcaSDan McDonald (U64)cmd->frame_phys_addr);
22792ffc8bcaSDan McDonald
22802ffc8bcaSDan McDonald ddi_put8(acc_handle,
22812ffc8bcaSDan McDonald &scsi_raid_io_sgl_ieee->Flags, (IEEE_SGE_FLAGS_CHAIN_ELEMENT |
22822ffc8bcaSDan McDonald MPI2_IEEE_SGE_FLAGS_IOCPLBNTA_ADDR));
22832ffc8bcaSDan McDonald /* LSI put hardcoded 1024 instead of MEGASAS_MAX_SZ_CHAIN_FRAME. */
22842ffc8bcaSDan McDonald ddi_put32(acc_handle, &scsi_raid_io_sgl_ieee->Length, 1024);
22852ffc8bcaSDan McDonald
22862ffc8bcaSDan McDonald con_log(CL_ANN1, (CE_NOTE,
22872ffc8bcaSDan McDonald "[MFI CMD PHY ADDRESS]:%" PRIx64,
22882ffc8bcaSDan McDonald scsi_raid_io_sgl_ieee->Address));
22892ffc8bcaSDan McDonald con_log(CL_ANN1, (CE_NOTE,
22902ffc8bcaSDan McDonald "[SGL Length]:%x", scsi_raid_io_sgl_ieee->Length));
22912ffc8bcaSDan McDonald con_log(CL_ANN1, (CE_NOTE, "[SGL Flags]:%x",
22922ffc8bcaSDan McDonald scsi_raid_io_sgl_ieee->Flags));
22932ffc8bcaSDan McDonald }
22942ffc8bcaSDan McDonald
22952ffc8bcaSDan McDonald
22962ffc8bcaSDan McDonald void
tbolt_complete_cmd(struct mrsas_instance * instance,struct mrsas_cmd * cmd)22972ffc8bcaSDan McDonald tbolt_complete_cmd(struct mrsas_instance *instance,
22982ffc8bcaSDan McDonald struct mrsas_cmd *cmd)
22992ffc8bcaSDan McDonald {
23002ffc8bcaSDan McDonald uint8_t status;
23012ffc8bcaSDan McDonald uint8_t extStatus;
2302091932b4SAndy Fiddaman uint8_t function;
23032ffc8bcaSDan McDonald uint8_t arm;
23042ffc8bcaSDan McDonald struct scsa_cmd *acmd;
23052ffc8bcaSDan McDonald struct scsi_pkt *pkt;
23062ffc8bcaSDan McDonald struct scsi_arq_status *arqstat;
23072ffc8bcaSDan McDonald Mpi2RaidSCSIIORequest_t *scsi_raid_io;
23082ffc8bcaSDan McDonald LD_LOAD_BALANCE_INFO *lbinfo;
23092ffc8bcaSDan McDonald ddi_acc_handle_t acc_handle =
23102ffc8bcaSDan McDonald instance->mpi2_frame_pool_dma_obj.acc_handle;
23112ffc8bcaSDan McDonald
23122ffc8bcaSDan McDonald scsi_raid_io = (Mpi2RaidSCSIIORequest_t *)cmd->scsi_io_request;
23132ffc8bcaSDan McDonald
23142ffc8bcaSDan McDonald status = ddi_get8(acc_handle, &scsi_raid_io->RaidContext.status);
23152ffc8bcaSDan McDonald extStatus = ddi_get8(acc_handle, &scsi_raid_io->RaidContext.extStatus);
23162ffc8bcaSDan McDonald
23172ffc8bcaSDan McDonald con_log(CL_DLEVEL3, (CE_NOTE, "status %x", status));
23182ffc8bcaSDan McDonald con_log(CL_DLEVEL3, (CE_NOTE, "extStatus %x", extStatus));
23192ffc8bcaSDan McDonald
23202ffc8bcaSDan McDonald if (status != MFI_STAT_OK) {
23212ffc8bcaSDan McDonald con_log(CL_ANN, (CE_WARN,
23222ffc8bcaSDan McDonald "IO Cmd Failed SMID %x", cmd->SMID));
23232ffc8bcaSDan McDonald } else {
23242ffc8bcaSDan McDonald con_log(CL_ANN, (CE_NOTE,
23252ffc8bcaSDan McDonald "IO Cmd Success SMID %x", cmd->SMID));
23262ffc8bcaSDan McDonald }
23272ffc8bcaSDan McDonald
23282ffc8bcaSDan McDonald /* regular commands */
23292ffc8bcaSDan McDonald
2330091932b4SAndy Fiddaman function = ddi_get8(acc_handle, &scsi_raid_io->Function);
2331091932b4SAndy Fiddaman DTRACE_PROBE3(tbolt_complete_cmd, uint8_t, function,
2332091932b4SAndy Fiddaman uint8_t, status, uint8_t, extStatus);
2333091932b4SAndy Fiddaman
2334091932b4SAndy Fiddaman switch (function) {
23352ffc8bcaSDan McDonald
23362ffc8bcaSDan McDonald case MPI2_FUNCTION_SCSI_IO_REQUEST : /* Fast Path IO. */
23372ffc8bcaSDan McDonald acmd = (struct scsa_cmd *)cmd->cmd;
23382ffc8bcaSDan McDonald lbinfo = &instance->load_balance_info[acmd->device_id];
23392ffc8bcaSDan McDonald
23402ffc8bcaSDan McDonald if (cmd->load_balance_flag & MEGASAS_LOAD_BALANCE_FLAG) {
23412ffc8bcaSDan McDonald arm = lbinfo->raid1DevHandle[0] ==
23422ffc8bcaSDan McDonald scsi_raid_io->DevHandle ? 0 : 1;
23432ffc8bcaSDan McDonald
23442ffc8bcaSDan McDonald lbinfo->scsi_pending_cmds[arm]--;
23452ffc8bcaSDan McDonald cmd->load_balance_flag &= ~MEGASAS_LOAD_BALANCE_FLAG;
23462ffc8bcaSDan McDonald }
23472ffc8bcaSDan McDonald con_log(CL_DLEVEL3, (CE_NOTE,
23482ffc8bcaSDan McDonald "FastPath IO Completion Success "));
23492ffc8bcaSDan McDonald /* FALLTHRU */
23502ffc8bcaSDan McDonald
23512ffc8bcaSDan McDonald case MPI2_FUNCTION_LD_IO_REQUEST : { /* Regular Path IO. */
23522ffc8bcaSDan McDonald acmd = (struct scsa_cmd *)cmd->cmd;
23532ffc8bcaSDan McDonald pkt = (struct scsi_pkt *)CMD2PKT(acmd);
23542ffc8bcaSDan McDonald
23552ffc8bcaSDan McDonald if (acmd->cmd_flags & CFLAG_DMAVALID) {
23562ffc8bcaSDan McDonald if (acmd->cmd_flags & CFLAG_CONSISTENT) {
23572ffc8bcaSDan McDonald (void) ddi_dma_sync(acmd->cmd_dmahandle,
23582ffc8bcaSDan McDonald acmd->cmd_dma_offset, acmd->cmd_dma_len,
23592ffc8bcaSDan McDonald DDI_DMA_SYNC_FORCPU);
23602ffc8bcaSDan McDonald }
23612ffc8bcaSDan McDonald }
23622ffc8bcaSDan McDonald
23632ffc8bcaSDan McDonald pkt->pkt_reason = CMD_CMPLT;
23642ffc8bcaSDan McDonald pkt->pkt_statistics = 0;
23652ffc8bcaSDan McDonald pkt->pkt_state = STATE_GOT_BUS | STATE_GOT_TARGET |
23662ffc8bcaSDan McDonald STATE_SENT_CMD | STATE_XFERRED_DATA | STATE_GOT_STATUS;
23672ffc8bcaSDan McDonald
23682ffc8bcaSDan McDonald con_log(CL_ANN, (CE_CONT, " CDB[0] = %x completed for %s: "
23692ffc8bcaSDan McDonald "size %lx SMID %x cmd_status %x", pkt->pkt_cdbp[0],
23702ffc8bcaSDan McDonald ((acmd->islogical) ? "LD" : "PD"),
23712ffc8bcaSDan McDonald acmd->cmd_dmacount, cmd->SMID, status));
23722ffc8bcaSDan McDonald
23732ffc8bcaSDan McDonald if (pkt->pkt_cdbp[0] == SCMD_INQUIRY) {
23742ffc8bcaSDan McDonald struct scsi_inquiry *inq;
23752ffc8bcaSDan McDonald
23762ffc8bcaSDan McDonald if (acmd->cmd_dmacount != 0) {
23772ffc8bcaSDan McDonald bp_mapin(acmd->cmd_buf);
23782ffc8bcaSDan McDonald inq = (struct scsi_inquiry *)
23792ffc8bcaSDan McDonald acmd->cmd_buf->b_un.b_addr;
23802ffc8bcaSDan McDonald
23812ffc8bcaSDan McDonald /* don't expose physical drives to OS */
23822ffc8bcaSDan McDonald if (acmd->islogical &&
23832ffc8bcaSDan McDonald (status == MFI_STAT_OK)) {
23842ffc8bcaSDan McDonald display_scsi_inquiry((caddr_t)inq);
23852ffc8bcaSDan McDonald } else if ((status == MFI_STAT_OK) &&
23862ffc8bcaSDan McDonald inq->inq_dtype == DTYPE_DIRECT) {
23872ffc8bcaSDan McDonald display_scsi_inquiry((caddr_t)inq);
23882ffc8bcaSDan McDonald } else {
23892ffc8bcaSDan McDonald /* for physical disk */
23902ffc8bcaSDan McDonald status = MFI_STAT_DEVICE_NOT_FOUND;
23912ffc8bcaSDan McDonald }
23922ffc8bcaSDan McDonald }
23932ffc8bcaSDan McDonald }
23942ffc8bcaSDan McDonald
23952ffc8bcaSDan McDonald switch (status) {
23962ffc8bcaSDan McDonald case MFI_STAT_OK:
23972ffc8bcaSDan McDonald pkt->pkt_scbp[0] = STATUS_GOOD;
23982ffc8bcaSDan McDonald break;
23992ffc8bcaSDan McDonald case MFI_STAT_LD_CC_IN_PROGRESS:
24002ffc8bcaSDan McDonald case MFI_STAT_LD_RECON_IN_PROGRESS:
24012ffc8bcaSDan McDonald pkt->pkt_scbp[0] = STATUS_GOOD;
24022ffc8bcaSDan McDonald break;
24032ffc8bcaSDan McDonald case MFI_STAT_LD_INIT_IN_PROGRESS:
24042ffc8bcaSDan McDonald pkt->pkt_reason = CMD_TRAN_ERR;
24052ffc8bcaSDan McDonald break;
24062ffc8bcaSDan McDonald case MFI_STAT_SCSI_IO_FAILED:
2407ff38cf9dSAndy Fiddaman dev_err(instance->dip, CE_WARN,
2408ff38cf9dSAndy Fiddaman "tbolt_complete_cmd: scsi_io failed");
24092ffc8bcaSDan McDonald pkt->pkt_reason = CMD_TRAN_ERR;
24102ffc8bcaSDan McDonald break;
24112ffc8bcaSDan McDonald case MFI_STAT_SCSI_DONE_WITH_ERROR:
24122ffc8bcaSDan McDonald con_log(CL_ANN, (CE_WARN,
24132ffc8bcaSDan McDonald "tbolt_complete_cmd: scsi_done with error"));
24142ffc8bcaSDan McDonald
24152ffc8bcaSDan McDonald pkt->pkt_reason = CMD_CMPLT;
24162ffc8bcaSDan McDonald ((struct scsi_status *)pkt->pkt_scbp)->sts_chk = 1;
24172ffc8bcaSDan McDonald
24182ffc8bcaSDan McDonald if (pkt->pkt_cdbp[0] == SCMD_TEST_UNIT_READY) {
24192ffc8bcaSDan McDonald con_log(CL_ANN,
24202ffc8bcaSDan McDonald (CE_WARN, "TEST_UNIT_READY fail"));
24212ffc8bcaSDan McDonald } else {
24222ffc8bcaSDan McDonald pkt->pkt_state |= STATE_ARQ_DONE;
24232ffc8bcaSDan McDonald arqstat = (void *)(pkt->pkt_scbp);
24242ffc8bcaSDan McDonald arqstat->sts_rqpkt_reason = CMD_CMPLT;
24252ffc8bcaSDan McDonald arqstat->sts_rqpkt_resid = 0;
24262ffc8bcaSDan McDonald arqstat->sts_rqpkt_state |=
24272ffc8bcaSDan McDonald STATE_GOT_BUS | STATE_GOT_TARGET
24282ffc8bcaSDan McDonald | STATE_SENT_CMD
24292ffc8bcaSDan McDonald | STATE_XFERRED_DATA;
24302ffc8bcaSDan McDonald *(uint8_t *)&arqstat->sts_rqpkt_status =
24312ffc8bcaSDan McDonald STATUS_GOOD;
24322ffc8bcaSDan McDonald con_log(CL_ANN1,
24332ffc8bcaSDan McDonald (CE_NOTE, "Copying Sense data %x",
24342ffc8bcaSDan McDonald cmd->SMID));
24352ffc8bcaSDan McDonald
24362ffc8bcaSDan McDonald ddi_rep_get8(acc_handle,
24372ffc8bcaSDan McDonald (uint8_t *)&(arqstat->sts_sensedata),
24382ffc8bcaSDan McDonald cmd->sense1,
24392ffc8bcaSDan McDonald sizeof (struct scsi_extended_sense),
24402ffc8bcaSDan McDonald DDI_DEV_AUTOINCR);
24412ffc8bcaSDan McDonald
24422ffc8bcaSDan McDonald }
24432ffc8bcaSDan McDonald break;
24442ffc8bcaSDan McDonald case MFI_STAT_LD_OFFLINE:
2445ff38cf9dSAndy Fiddaman dev_err(instance->dip, CE_WARN,
24462ffc8bcaSDan McDonald "tbolt_complete_cmd: ld offline "
24472ffc8bcaSDan McDonald "CDB[0]=0x%x targetId=0x%x devhandle=0x%x",
24482ffc8bcaSDan McDonald /* UNDO: */
24492ffc8bcaSDan McDonald ddi_get8(acc_handle, &scsi_raid_io->CDB.CDB32[0]),
24502ffc8bcaSDan McDonald
24512ffc8bcaSDan McDonald ddi_get16(acc_handle,
24522ffc8bcaSDan McDonald &scsi_raid_io->RaidContext.ldTargetId),
24532ffc8bcaSDan McDonald
24542ffc8bcaSDan McDonald ddi_get16(acc_handle, &scsi_raid_io->DevHandle));
24552ffc8bcaSDan McDonald
24562ffc8bcaSDan McDonald pkt->pkt_reason = CMD_DEV_GONE;
24572ffc8bcaSDan McDonald pkt->pkt_statistics = STAT_DISCON;
24582ffc8bcaSDan McDonald break;
24592ffc8bcaSDan McDonald case MFI_STAT_DEVICE_NOT_FOUND:
24602ffc8bcaSDan McDonald con_log(CL_ANN, (CE_CONT,
24612ffc8bcaSDan McDonald "tbolt_complete_cmd: device not found error"));
24622ffc8bcaSDan McDonald pkt->pkt_reason = CMD_DEV_GONE;
24632ffc8bcaSDan McDonald pkt->pkt_statistics = STAT_DISCON;
24642ffc8bcaSDan McDonald break;
24652ffc8bcaSDan McDonald
24662ffc8bcaSDan McDonald case MFI_STAT_LD_LBA_OUT_OF_RANGE:
24672ffc8bcaSDan McDonald pkt->pkt_state |= STATE_ARQ_DONE;
24682ffc8bcaSDan McDonald pkt->pkt_reason = CMD_CMPLT;
24692ffc8bcaSDan McDonald ((struct scsi_status *)pkt->pkt_scbp)->sts_chk = 1;
24702ffc8bcaSDan McDonald
24712ffc8bcaSDan McDonald arqstat = (void *)(pkt->pkt_scbp);
24722ffc8bcaSDan McDonald arqstat->sts_rqpkt_reason = CMD_CMPLT;
24732ffc8bcaSDan McDonald arqstat->sts_rqpkt_resid = 0;
24742ffc8bcaSDan McDonald arqstat->sts_rqpkt_state |= STATE_GOT_BUS
24752ffc8bcaSDan McDonald | STATE_GOT_TARGET | STATE_SENT_CMD
24762ffc8bcaSDan McDonald | STATE_XFERRED_DATA;
24772ffc8bcaSDan McDonald *(uint8_t *)&arqstat->sts_rqpkt_status = STATUS_GOOD;
24782ffc8bcaSDan McDonald
24792ffc8bcaSDan McDonald arqstat->sts_sensedata.es_valid = 1;
24802ffc8bcaSDan McDonald arqstat->sts_sensedata.es_key = KEY_ILLEGAL_REQUEST;
24812ffc8bcaSDan McDonald arqstat->sts_sensedata.es_class = CLASS_EXTENDED_SENSE;
24822ffc8bcaSDan McDonald
24832ffc8bcaSDan McDonald /*
24842ffc8bcaSDan McDonald * LOGICAL BLOCK ADDRESS OUT OF RANGE:
24852ffc8bcaSDan McDonald * ASC: 0x21h; ASCQ: 0x00h;
24862ffc8bcaSDan McDonald */
24872ffc8bcaSDan McDonald arqstat->sts_sensedata.es_add_code = 0x21;
24882ffc8bcaSDan McDonald arqstat->sts_sensedata.es_qual_code = 0x00;
24892ffc8bcaSDan McDonald break;
24902ffc8bcaSDan McDonald case MFI_STAT_INVALID_CMD:
24912ffc8bcaSDan McDonald case MFI_STAT_INVALID_DCMD:
24922ffc8bcaSDan McDonald case MFI_STAT_INVALID_PARAMETER:
24932ffc8bcaSDan McDonald case MFI_STAT_INVALID_SEQUENCE_NUMBER:
24942ffc8bcaSDan McDonald default:
2495ff38cf9dSAndy Fiddaman dev_err(instance->dip, CE_WARN,
2496ff38cf9dSAndy Fiddaman "tbolt_complete_cmd: Unknown status!");
24972ffc8bcaSDan McDonald pkt->pkt_reason = CMD_TRAN_ERR;
24982ffc8bcaSDan McDonald
24992ffc8bcaSDan McDonald break;
25002ffc8bcaSDan McDonald }
25012ffc8bcaSDan McDonald
25022ffc8bcaSDan McDonald atomic_add_16(&instance->fw_outstanding, (-1));
25032ffc8bcaSDan McDonald
25042ffc8bcaSDan McDonald (void) mrsas_common_check(instance, cmd);
25052ffc8bcaSDan McDonald if (acmd->cmd_dmahandle) {
25062ffc8bcaSDan McDonald if (mrsas_check_dma_handle(acmd->cmd_dmahandle) !=
25072ffc8bcaSDan McDonald DDI_SUCCESS) {
25082ffc8bcaSDan McDonald ddi_fm_service_impact(instance->dip,
25092ffc8bcaSDan McDonald DDI_SERVICE_UNAFFECTED);
25102ffc8bcaSDan McDonald pkt->pkt_reason = CMD_TRAN_ERR;
25112ffc8bcaSDan McDonald pkt->pkt_statistics = 0;
25122ffc8bcaSDan McDonald }
25132ffc8bcaSDan McDonald }
25142ffc8bcaSDan McDonald
25152ffc8bcaSDan McDonald /* Call the callback routine */
25162ffc8bcaSDan McDonald if (((pkt->pkt_flags & FLAG_NOINTR) == 0) && pkt->pkt_comp)
25172ffc8bcaSDan McDonald (*pkt->pkt_comp)(pkt);
25182ffc8bcaSDan McDonald
25192ffc8bcaSDan McDonald con_log(CL_ANN1, (CE_NOTE, "Free smid %x", cmd->SMID));
25202ffc8bcaSDan McDonald
25212ffc8bcaSDan McDonald ddi_put8(acc_handle, &scsi_raid_io->RaidContext.status, 0);
25222ffc8bcaSDan McDonald
25232ffc8bcaSDan McDonald ddi_put8(acc_handle, &scsi_raid_io->RaidContext.extStatus, 0);
25242ffc8bcaSDan McDonald
25252ffc8bcaSDan McDonald return_raid_msg_pkt(instance, cmd);
25262ffc8bcaSDan McDonald break;
25272ffc8bcaSDan McDonald }
25282ffc8bcaSDan McDonald case MPI2_FUNCTION_PASSTHRU_IO_REQUEST: /* MFA command. */
25292ffc8bcaSDan McDonald
25302ffc8bcaSDan McDonald if (cmd->frame->dcmd.opcode == MR_DCMD_LD_MAP_GET_INFO &&
25312ffc8bcaSDan McDonald cmd->frame->dcmd.mbox.b[1] == 1) {
25322ffc8bcaSDan McDonald
25332ffc8bcaSDan McDonald mutex_enter(&instance->sync_map_mtx);
25342ffc8bcaSDan McDonald
25352ffc8bcaSDan McDonald con_log(CL_ANN, (CE_NOTE,
25362ffc8bcaSDan McDonald "LDMAP sync command SMID RECEIVED 0x%X",
25372ffc8bcaSDan McDonald cmd->SMID));
25382ffc8bcaSDan McDonald if (cmd->frame->hdr.cmd_status != 0) {
2539ff38cf9dSAndy Fiddaman dev_err(instance->dip, CE_WARN,
25402ffc8bcaSDan McDonald "map sync failed, status = 0x%x.",
25412ffc8bcaSDan McDonald cmd->frame->hdr.cmd_status);
25422ffc8bcaSDan McDonald } else {
25432ffc8bcaSDan McDonald instance->map_id++;
2544ff38cf9dSAndy Fiddaman con_log(CL_ANN1, (CE_NOTE,
25452ffc8bcaSDan McDonald "map sync received, switched map_id to %"
2546ff38cf9dSAndy Fiddaman PRIu64, instance->map_id));
25472ffc8bcaSDan McDonald }
25482ffc8bcaSDan McDonald
2549e65bc174SAndy Fiddaman if (MR_ValidateMapInfo(
2550e65bc174SAndy Fiddaman instance->ld_map[instance->map_id & 1],
25512ffc8bcaSDan McDonald instance->load_balance_info)) {
25522ffc8bcaSDan McDonald instance->fast_path_io = 1;
25532ffc8bcaSDan McDonald } else {
25542ffc8bcaSDan McDonald instance->fast_path_io = 0;
25552ffc8bcaSDan McDonald }
25562ffc8bcaSDan McDonald
25572ffc8bcaSDan McDonald con_log(CL_ANN, (CE_NOTE,
25582ffc8bcaSDan McDonald "instance->fast_path_io %d",
25592ffc8bcaSDan McDonald instance->fast_path_io));
25602ffc8bcaSDan McDonald
25612ffc8bcaSDan McDonald instance->unroll.syncCmd = 0;
25622ffc8bcaSDan McDonald
25632ffc8bcaSDan McDonald if (instance->map_update_cmd == cmd) {
25642ffc8bcaSDan McDonald return_raid_msg_pkt(instance, cmd);
25652ffc8bcaSDan McDonald atomic_add_16(&instance->fw_outstanding, (-1));
25662ffc8bcaSDan McDonald (void) mrsas_tbolt_sync_map_info(instance);
25672ffc8bcaSDan McDonald }
25682ffc8bcaSDan McDonald
2569ff38cf9dSAndy Fiddaman con_log(CL_ANN1, (CE_NOTE,
2570ff38cf9dSAndy Fiddaman "LDMAP sync completed, ldcount=%d",
2571ff38cf9dSAndy Fiddaman instance->ld_map[instance->map_id & 1]
2572ff38cf9dSAndy Fiddaman ->raidMap.ldCount));
25732ffc8bcaSDan McDonald mutex_exit(&instance->sync_map_mtx);
25742ffc8bcaSDan McDonald break;
25752ffc8bcaSDan McDonald }
25762ffc8bcaSDan McDonald
25772ffc8bcaSDan McDonald if (cmd->frame->dcmd.opcode == MR_DCMD_CTRL_EVENT_WAIT) {
25782ffc8bcaSDan McDonald con_log(CL_ANN1, (CE_CONT,
25792ffc8bcaSDan McDonald "AEN command SMID RECEIVED 0x%X",
25802ffc8bcaSDan McDonald cmd->SMID));
25812ffc8bcaSDan McDonald if ((instance->aen_cmd == cmd) &&
25822ffc8bcaSDan McDonald (instance->aen_cmd->abort_aen)) {
25832ffc8bcaSDan McDonald con_log(CL_ANN, (CE_WARN, "mrsas_softintr: "
25842ffc8bcaSDan McDonald "aborted_aen returned"));
25852ffc8bcaSDan McDonald } else {
25862ffc8bcaSDan McDonald atomic_add_16(&instance->fw_outstanding, (-1));
25872ffc8bcaSDan McDonald service_mfi_aen(instance, cmd);
25882ffc8bcaSDan McDonald }
25892ffc8bcaSDan McDonald }
25902ffc8bcaSDan McDonald
25912ffc8bcaSDan McDonald if (cmd->sync_cmd == MRSAS_TRUE) {
25922ffc8bcaSDan McDonald con_log(CL_ANN1, (CE_CONT,
25932ffc8bcaSDan McDonald "Sync-mode Command Response SMID RECEIVED 0x%X",
25942ffc8bcaSDan McDonald cmd->SMID));
25952ffc8bcaSDan McDonald
25962ffc8bcaSDan McDonald tbolt_complete_cmd_in_sync_mode(instance, cmd);
25972ffc8bcaSDan McDonald } else {
25982ffc8bcaSDan McDonald con_log(CL_ANN, (CE_CONT,
25992ffc8bcaSDan McDonald "tbolt_complete_cmd: Wrong SMID RECEIVED 0x%X",
26002ffc8bcaSDan McDonald cmd->SMID));
26012ffc8bcaSDan McDonald }
26022ffc8bcaSDan McDonald break;
26032ffc8bcaSDan McDonald default:
26042ffc8bcaSDan McDonald mrsas_fm_ereport(instance, DDI_FM_DEVICE_NO_RESPONSE);
26052ffc8bcaSDan McDonald ddi_fm_service_impact(instance->dip, DDI_SERVICE_LOST);
26062ffc8bcaSDan McDonald
26072ffc8bcaSDan McDonald /* free message */
26082ffc8bcaSDan McDonald con_log(CL_ANN,
26092ffc8bcaSDan McDonald (CE_NOTE, "tbolt_complete_cmd: Unknown Type!!!!!!!!"));
26102ffc8bcaSDan McDonald break;
26112ffc8bcaSDan McDonald }
26122ffc8bcaSDan McDonald }
26132ffc8bcaSDan McDonald
26142ffc8bcaSDan McDonald uint_t
mr_sas_tbolt_process_outstanding_cmd(struct mrsas_instance * instance)26152ffc8bcaSDan McDonald mr_sas_tbolt_process_outstanding_cmd(struct mrsas_instance *instance)
26162ffc8bcaSDan McDonald {
26172ffc8bcaSDan McDonald uint8_t replyType;
26182ffc8bcaSDan McDonald Mpi2SCSIIOSuccessReplyDescriptor_t *replyDesc;
26192ffc8bcaSDan McDonald Mpi2ReplyDescriptorsUnion_t *desc;
26202ffc8bcaSDan McDonald uint16_t smid;
26212ffc8bcaSDan McDonald union desc_value d_val;
26222ffc8bcaSDan McDonald struct mrsas_cmd *cmd;
26232ffc8bcaSDan McDonald
26242ffc8bcaSDan McDonald struct mrsas_header *hdr;
26252ffc8bcaSDan McDonald struct scsi_pkt *pkt;
26262ffc8bcaSDan McDonald
26272ffc8bcaSDan McDonald (void) ddi_dma_sync(instance->reply_desc_dma_obj.dma_handle,
26282ffc8bcaSDan McDonald 0, 0, DDI_DMA_SYNC_FORDEV);
26292ffc8bcaSDan McDonald
26302ffc8bcaSDan McDonald (void) ddi_dma_sync(instance->reply_desc_dma_obj.dma_handle,
26312ffc8bcaSDan McDonald 0, 0, DDI_DMA_SYNC_FORCPU);
26322ffc8bcaSDan McDonald
26332ffc8bcaSDan McDonald desc = instance->reply_frame_pool;
26342ffc8bcaSDan McDonald desc += instance->reply_read_index;
26352ffc8bcaSDan McDonald
26362ffc8bcaSDan McDonald replyDesc = (MPI2_SCSI_IO_SUCCESS_REPLY_DESCRIPTOR *)desc;
26372ffc8bcaSDan McDonald replyType = replyDesc->ReplyFlags &
26382ffc8bcaSDan McDonald MPI2_RPY_DESCRIPT_FLAGS_TYPE_MASK;
26392ffc8bcaSDan McDonald
26402ffc8bcaSDan McDonald if (replyType == MPI2_RPY_DESCRIPT_FLAGS_UNUSED)
26412ffc8bcaSDan McDonald return (DDI_INTR_UNCLAIMED);
26422ffc8bcaSDan McDonald
26432ffc8bcaSDan McDonald if (mrsas_check_dma_handle(instance->mfi_internal_dma_obj.dma_handle)
26442ffc8bcaSDan McDonald != DDI_SUCCESS) {
26452ffc8bcaSDan McDonald mrsas_fm_ereport(instance, DDI_FM_DEVICE_NO_RESPONSE);
26462ffc8bcaSDan McDonald ddi_fm_service_impact(instance->dip, DDI_SERVICE_LOST);
26472ffc8bcaSDan McDonald con_log(CL_ANN1,
26482ffc8bcaSDan McDonald (CE_WARN, "mr_sas_tbolt_process_outstanding_cmd(): "
26492ffc8bcaSDan McDonald "FMA check, returning DDI_INTR_UNCLAIMED"));
26502ffc8bcaSDan McDonald return (DDI_INTR_CLAIMED);
26512ffc8bcaSDan McDonald }
26522ffc8bcaSDan McDonald
26532ffc8bcaSDan McDonald con_log(CL_ANN1, (CE_NOTE, "Reply Desc = %p Words = %" PRIx64,
26542ffc8bcaSDan McDonald (void *)desc, desc->Words));
26552ffc8bcaSDan McDonald
26562ffc8bcaSDan McDonald d_val.word = desc->Words;
26572ffc8bcaSDan McDonald
26582ffc8bcaSDan McDonald
26592ffc8bcaSDan McDonald /* Read Reply descriptor */
26602ffc8bcaSDan McDonald while ((d_val.u1.low != 0xffffffff) &&
26612ffc8bcaSDan McDonald (d_val.u1.high != 0xffffffff)) {
26622ffc8bcaSDan McDonald
26632ffc8bcaSDan McDonald (void) ddi_dma_sync(instance->reply_desc_dma_obj.dma_handle,
26642ffc8bcaSDan McDonald 0, 0, DDI_DMA_SYNC_FORCPU);
26652ffc8bcaSDan McDonald
26662ffc8bcaSDan McDonald smid = replyDesc->SMID;
26672ffc8bcaSDan McDonald
26682ffc8bcaSDan McDonald if (!smid || smid > instance->max_fw_cmds + 1) {
26692ffc8bcaSDan McDonald con_log(CL_ANN1, (CE_NOTE,
26702ffc8bcaSDan McDonald "Reply Desc at Break = %p Words = %" PRIx64,
26712ffc8bcaSDan McDonald (void *)desc, desc->Words));
26722ffc8bcaSDan McDonald break;
26732ffc8bcaSDan McDonald }
26742ffc8bcaSDan McDonald
26752ffc8bcaSDan McDonald cmd = instance->cmd_list[smid - 1];
26762ffc8bcaSDan McDonald if (!cmd) {
26772ffc8bcaSDan McDonald con_log(CL_ANN1, (CE_NOTE, "mr_sas_tbolt_process_"
26782ffc8bcaSDan McDonald "outstanding_cmd: Invalid command "
26792ffc8bcaSDan McDonald " or Poll commad Received in completion path"));
26802ffc8bcaSDan McDonald } else {
26812ffc8bcaSDan McDonald mutex_enter(&instance->cmd_pend_mtx);
26822ffc8bcaSDan McDonald if (cmd->sync_cmd == MRSAS_TRUE) {
26832ffc8bcaSDan McDonald hdr = (struct mrsas_header *)&cmd->frame->hdr;
26842ffc8bcaSDan McDonald if (hdr) {
26852ffc8bcaSDan McDonald con_log(CL_ANN1, (CE_NOTE, "mr_sas_"
26862ffc8bcaSDan McDonald "tbolt_process_outstanding_cmd:"
26872ffc8bcaSDan McDonald " mlist_del_init(&cmd->list)."));
26882ffc8bcaSDan McDonald mlist_del_init(&cmd->list);
26892ffc8bcaSDan McDonald }
26902ffc8bcaSDan McDonald } else {
26912ffc8bcaSDan McDonald pkt = cmd->pkt;
26922ffc8bcaSDan McDonald if (pkt) {
26932ffc8bcaSDan McDonald con_log(CL_ANN1, (CE_NOTE, "mr_sas_"
26942ffc8bcaSDan McDonald "tbolt_process_outstanding_cmd:"
26952ffc8bcaSDan McDonald "mlist_del_init(&cmd->list)."));
26962ffc8bcaSDan McDonald mlist_del_init(&cmd->list);
26972ffc8bcaSDan McDonald }
26982ffc8bcaSDan McDonald }
26992ffc8bcaSDan McDonald
27002ffc8bcaSDan McDonald mutex_exit(&instance->cmd_pend_mtx);
27012ffc8bcaSDan McDonald
27022ffc8bcaSDan McDonald tbolt_complete_cmd(instance, cmd);
27032ffc8bcaSDan McDonald }
27042ffc8bcaSDan McDonald /* set it back to all 1s. */
27052ffc8bcaSDan McDonald desc->Words = -1LL;
27062ffc8bcaSDan McDonald
27072ffc8bcaSDan McDonald instance->reply_read_index++;
27082ffc8bcaSDan McDonald
27092ffc8bcaSDan McDonald if (instance->reply_read_index >= (instance->reply_q_depth)) {
27102ffc8bcaSDan McDonald con_log(CL_ANN1, (CE_NOTE, "wrap around"));
27112ffc8bcaSDan McDonald instance->reply_read_index = 0;
27122ffc8bcaSDan McDonald }
27132ffc8bcaSDan McDonald
27142ffc8bcaSDan McDonald /* Get the next reply descriptor */
27152ffc8bcaSDan McDonald if (!instance->reply_read_index)
27162ffc8bcaSDan McDonald desc = instance->reply_frame_pool;
27172ffc8bcaSDan McDonald else
27182ffc8bcaSDan McDonald desc++;
27192ffc8bcaSDan McDonald
27202ffc8bcaSDan McDonald replyDesc = (MPI2_SCSI_IO_SUCCESS_REPLY_DESCRIPTOR *)desc;
27212ffc8bcaSDan McDonald
27222ffc8bcaSDan McDonald d_val.word = desc->Words;
27232ffc8bcaSDan McDonald
27242ffc8bcaSDan McDonald con_log(CL_ANN1, (CE_NOTE,
27252ffc8bcaSDan McDonald "Next Reply Desc = %p Words = %" PRIx64,
27262ffc8bcaSDan McDonald (void *)desc, desc->Words));
27272ffc8bcaSDan McDonald
27282ffc8bcaSDan McDonald replyType = replyDesc->ReplyFlags &
27292ffc8bcaSDan McDonald MPI2_RPY_DESCRIPT_FLAGS_TYPE_MASK;
27302ffc8bcaSDan McDonald
27312ffc8bcaSDan McDonald if (replyType == MPI2_RPY_DESCRIPT_FLAGS_UNUSED)
27322ffc8bcaSDan McDonald break;
27332ffc8bcaSDan McDonald
27342ffc8bcaSDan McDonald } /* End of while loop. */
27352ffc8bcaSDan McDonald
27362ffc8bcaSDan McDonald /* update replyIndex to FW */
27372ffc8bcaSDan McDonald WR_MPI2_REPLY_POST_INDEX(instance->reply_read_index, instance);
27382ffc8bcaSDan McDonald
27392ffc8bcaSDan McDonald
27402ffc8bcaSDan McDonald (void) ddi_dma_sync(instance->reply_desc_dma_obj.dma_handle,
27412ffc8bcaSDan McDonald 0, 0, DDI_DMA_SYNC_FORDEV);
27422ffc8bcaSDan McDonald
27432ffc8bcaSDan McDonald (void) ddi_dma_sync(instance->reply_desc_dma_obj.dma_handle,
27442ffc8bcaSDan McDonald 0, 0, DDI_DMA_SYNC_FORCPU);
27452ffc8bcaSDan McDonald return (DDI_INTR_CLAIMED);
27462ffc8bcaSDan McDonald }
27472ffc8bcaSDan McDonald
27482ffc8bcaSDan McDonald
27492ffc8bcaSDan McDonald
27502ffc8bcaSDan McDonald
27512ffc8bcaSDan McDonald /*
27522ffc8bcaSDan McDonald * complete_cmd_in_sync_mode - Completes an internal command
27532ffc8bcaSDan McDonald * @instance: Adapter soft state
27542ffc8bcaSDan McDonald * @cmd: Command to be completed
27552ffc8bcaSDan McDonald *
27562ffc8bcaSDan McDonald * The issue_cmd_in_sync_mode() function waits for a command to complete
27572ffc8bcaSDan McDonald * after it issues a command. This function wakes up that waiting routine by
27582ffc8bcaSDan McDonald * calling wake_up() on the wait queue.
27592ffc8bcaSDan McDonald */
27602ffc8bcaSDan McDonald void
tbolt_complete_cmd_in_sync_mode(struct mrsas_instance * instance,struct mrsas_cmd * cmd)27612ffc8bcaSDan McDonald tbolt_complete_cmd_in_sync_mode(struct mrsas_instance *instance,
27622ffc8bcaSDan McDonald struct mrsas_cmd *cmd)
27632ffc8bcaSDan McDonald {
27642ffc8bcaSDan McDonald
27652ffc8bcaSDan McDonald cmd->cmd_status = ddi_get8(cmd->frame_dma_obj.acc_handle,
27662ffc8bcaSDan McDonald &cmd->frame->io.cmd_status);
27672ffc8bcaSDan McDonald
27682ffc8bcaSDan McDonald cmd->sync_cmd = MRSAS_FALSE;
27692ffc8bcaSDan McDonald
27702ffc8bcaSDan McDonald mutex_enter(&instance->int_cmd_mtx);
27712ffc8bcaSDan McDonald if (cmd->cmd_status == ENODATA) {
27722ffc8bcaSDan McDonald cmd->cmd_status = 0;
27732ffc8bcaSDan McDonald }
27742ffc8bcaSDan McDonald cv_broadcast(&instance->int_cmd_cv);
27752ffc8bcaSDan McDonald mutex_exit(&instance->int_cmd_mtx);
27762ffc8bcaSDan McDonald
27772ffc8bcaSDan McDonald }
27782ffc8bcaSDan McDonald
27792ffc8bcaSDan McDonald /*
27802ffc8bcaSDan McDonald * mrsas_tbolt_get_ld_map_info - Returns ld_map structure
27812ffc8bcaSDan McDonald * instance: Adapter soft state
27822ffc8bcaSDan McDonald *
27832ffc8bcaSDan McDonald * Issues an internal command (DCMD) to get the FW's controller PD
27842ffc8bcaSDan McDonald * list structure. This information is mainly used to find out SYSTEM
27852ffc8bcaSDan McDonald * supported by the FW.
27862ffc8bcaSDan McDonald */
27872ffc8bcaSDan McDonald int
mrsas_tbolt_get_ld_map_info(struct mrsas_instance * instance)27882ffc8bcaSDan McDonald mrsas_tbolt_get_ld_map_info(struct mrsas_instance *instance)
27892ffc8bcaSDan McDonald {
27902ffc8bcaSDan McDonald int ret = 0;
27912ffc8bcaSDan McDonald struct mrsas_cmd *cmd = NULL;
27922ffc8bcaSDan McDonald struct mrsas_dcmd_frame *dcmd;
27932ffc8bcaSDan McDonald MR_FW_RAID_MAP_ALL *ci;
27942ffc8bcaSDan McDonald uint32_t ci_h = 0;
27952ffc8bcaSDan McDonald U32 size_map_info;
27962ffc8bcaSDan McDonald
27972ffc8bcaSDan McDonald cmd = get_raid_msg_pkt(instance);
27982ffc8bcaSDan McDonald
27992ffc8bcaSDan McDonald if (cmd == NULL) {
2800ff38cf9dSAndy Fiddaman dev_err(instance->dip, CE_WARN,
28012ffc8bcaSDan McDonald "Failed to get a cmd from free-pool in get_ld_map_info()");
28022ffc8bcaSDan McDonald return (DDI_FAILURE);
28032ffc8bcaSDan McDonald }
28042ffc8bcaSDan McDonald
28052ffc8bcaSDan McDonald dcmd = &cmd->frame->dcmd;
28062ffc8bcaSDan McDonald
28072ffc8bcaSDan McDonald size_map_info = sizeof (MR_FW_RAID_MAP) +
28082ffc8bcaSDan McDonald (sizeof (MR_LD_SPAN_MAP) *
28092ffc8bcaSDan McDonald (MAX_LOGICAL_DRIVES - 1));
28102ffc8bcaSDan McDonald
28112ffc8bcaSDan McDonald con_log(CL_ANN, (CE_NOTE,
28122ffc8bcaSDan McDonald "size_map_info : 0x%x", size_map_info));
28132ffc8bcaSDan McDonald
2814e65bc174SAndy Fiddaman ci = instance->ld_map[instance->map_id & 1];
2815e65bc174SAndy Fiddaman ci_h = instance->ld_map_phy[instance->map_id & 1];
28162ffc8bcaSDan McDonald
28172ffc8bcaSDan McDonald if (!ci) {
2818ff38cf9dSAndy Fiddaman dev_err(instance->dip, CE_WARN,
2819ff38cf9dSAndy Fiddaman "Failed to alloc mem for ld_map_info");
28202ffc8bcaSDan McDonald return_raid_msg_pkt(instance, cmd);
28212ffc8bcaSDan McDonald return (-1);
28222ffc8bcaSDan McDonald }
28232ffc8bcaSDan McDonald
28242ffc8bcaSDan McDonald bzero(ci, sizeof (*ci));
28252ffc8bcaSDan McDonald bzero(dcmd->mbox.b, DCMD_MBOX_SZ);
28262ffc8bcaSDan McDonald
28272ffc8bcaSDan McDonald dcmd->cmd = MFI_CMD_OP_DCMD;
28282ffc8bcaSDan McDonald dcmd->cmd_status = 0xFF;
28292ffc8bcaSDan McDonald dcmd->sge_count = 1;
28302ffc8bcaSDan McDonald dcmd->flags = MFI_FRAME_DIR_READ;
28312ffc8bcaSDan McDonald dcmd->timeout = 0;
28322ffc8bcaSDan McDonald dcmd->pad_0 = 0;
28332ffc8bcaSDan McDonald dcmd->data_xfer_len = size_map_info;
28342ffc8bcaSDan McDonald dcmd->opcode = MR_DCMD_LD_MAP_GET_INFO;
28352ffc8bcaSDan McDonald dcmd->sgl.sge32[0].phys_addr = ci_h;
28362ffc8bcaSDan McDonald dcmd->sgl.sge32[0].length = size_map_info;
28372ffc8bcaSDan McDonald
28382ffc8bcaSDan McDonald
28392ffc8bcaSDan McDonald mr_sas_tbolt_build_mfi_cmd(instance, cmd);
28402ffc8bcaSDan McDonald
28412ffc8bcaSDan McDonald if (!instance->func_ptr->issue_cmd_in_poll_mode(instance, cmd)) {
28422ffc8bcaSDan McDonald ret = 0;
28432ffc8bcaSDan McDonald con_log(CL_ANN1, (CE_NOTE, "Get LD Map Info success"));
28442ffc8bcaSDan McDonald } else {
2845ff38cf9dSAndy Fiddaman dev_err(instance->dip, CE_WARN, "Get LD Map Info failed");
28462ffc8bcaSDan McDonald ret = -1;
28472ffc8bcaSDan McDonald }
28482ffc8bcaSDan McDonald
28492ffc8bcaSDan McDonald return_raid_msg_pkt(instance, cmd);
28502ffc8bcaSDan McDonald
28512ffc8bcaSDan McDonald return (ret);
28522ffc8bcaSDan McDonald }
28532ffc8bcaSDan McDonald
28542ffc8bcaSDan McDonald void
mrsas_dump_reply_desc(struct mrsas_instance * instance)28552ffc8bcaSDan McDonald mrsas_dump_reply_desc(struct mrsas_instance *instance)
28562ffc8bcaSDan McDonald {
28572ffc8bcaSDan McDonald uint32_t i;
28582ffc8bcaSDan McDonald MPI2_REPLY_DESCRIPTORS_UNION *reply_desc;
28592ffc8bcaSDan McDonald union desc_value d_val;
28602ffc8bcaSDan McDonald
28612ffc8bcaSDan McDonald reply_desc = instance->reply_frame_pool;
28622ffc8bcaSDan McDonald
28632ffc8bcaSDan McDonald for (i = 0; i < instance->reply_q_depth; i++, reply_desc++) {
28642ffc8bcaSDan McDonald d_val.word = reply_desc->Words;
28652ffc8bcaSDan McDonald con_log(CL_DLEVEL3, (CE_NOTE,
28662ffc8bcaSDan McDonald "i=%d, %x:%x",
28672ffc8bcaSDan McDonald i, d_val.u1.high, d_val.u1.low));
28682ffc8bcaSDan McDonald }
28692ffc8bcaSDan McDonald }
28702ffc8bcaSDan McDonald
28712ffc8bcaSDan McDonald /*
28722ffc8bcaSDan McDonald * mrsas_tbolt_command_create - Create command for fast path.
28732ffc8bcaSDan McDonald * @io_info: MegaRAID IO request packet pointer.
28742ffc8bcaSDan McDonald * @ref_tag: Reference tag for RD/WRPROTECT
28752ffc8bcaSDan McDonald *
28762ffc8bcaSDan McDonald * Create the command for fast path.
28772ffc8bcaSDan McDonald */
28782ffc8bcaSDan McDonald void
mrsas_tbolt_prepare_cdb(struct mrsas_instance * instance,U8 cdb[],struct IO_REQUEST_INFO * io_info,Mpi2RaidSCSIIORequest_t * scsi_io_request,U32 ref_tag)28792ffc8bcaSDan McDonald mrsas_tbolt_prepare_cdb(struct mrsas_instance *instance, U8 cdb[],
28802ffc8bcaSDan McDonald struct IO_REQUEST_INFO *io_info, Mpi2RaidSCSIIORequest_t *scsi_io_request,
28812ffc8bcaSDan McDonald U32 ref_tag)
28822ffc8bcaSDan McDonald {
28832ffc8bcaSDan McDonald uint16_t EEDPFlags;
28842ffc8bcaSDan McDonald uint32_t Control;
28852ffc8bcaSDan McDonald ddi_acc_handle_t acc_handle =
28862ffc8bcaSDan McDonald instance->mpi2_frame_pool_dma_obj.acc_handle;
28872ffc8bcaSDan McDonald
28882ffc8bcaSDan McDonald /* Prepare 32-byte CDB if DIF is supported on this device */
28892ffc8bcaSDan McDonald con_log(CL_ANN, (CE_NOTE, "Prepare DIF CDB"));
28902ffc8bcaSDan McDonald
28912ffc8bcaSDan McDonald bzero(cdb, 32);
28922ffc8bcaSDan McDonald
28932ffc8bcaSDan McDonald cdb[0] = MRSAS_SCSI_VARIABLE_LENGTH_CMD;
28942ffc8bcaSDan McDonald
28952ffc8bcaSDan McDonald
28962ffc8bcaSDan McDonald cdb[7] = MRSAS_SCSI_ADDL_CDB_LEN;
28972ffc8bcaSDan McDonald
28982ffc8bcaSDan McDonald if (io_info->isRead)
28992ffc8bcaSDan McDonald cdb[9] = MRSAS_SCSI_SERVICE_ACTION_READ32;
29002ffc8bcaSDan McDonald else
29012ffc8bcaSDan McDonald cdb[9] = MRSAS_SCSI_SERVICE_ACTION_WRITE32;
29022ffc8bcaSDan McDonald
29032ffc8bcaSDan McDonald /* Verify within linux driver, set to MEGASAS_RD_WR_PROTECT_CHECK_ALL */
29042ffc8bcaSDan McDonald cdb[10] = MRSAS_RD_WR_PROTECT;
29052ffc8bcaSDan McDonald
29062ffc8bcaSDan McDonald /* LOGICAL BLOCK ADDRESS */
29072ffc8bcaSDan McDonald cdb[12] = (U8)(((io_info->pdBlock) >> 56) & 0xff);
29082ffc8bcaSDan McDonald cdb[13] = (U8)(((io_info->pdBlock) >> 48) & 0xff);
29092ffc8bcaSDan McDonald cdb[14] = (U8)(((io_info->pdBlock) >> 40) & 0xff);
29102ffc8bcaSDan McDonald cdb[15] = (U8)(((io_info->pdBlock) >> 32) & 0xff);
29112ffc8bcaSDan McDonald cdb[16] = (U8)(((io_info->pdBlock) >> 24) & 0xff);
29122ffc8bcaSDan McDonald cdb[17] = (U8)(((io_info->pdBlock) >> 16) & 0xff);
29132ffc8bcaSDan McDonald cdb[18] = (U8)(((io_info->pdBlock) >> 8) & 0xff);
29142ffc8bcaSDan McDonald cdb[19] = (U8)((io_info->pdBlock) & 0xff);
29152ffc8bcaSDan McDonald
29162ffc8bcaSDan McDonald /* Logical block reference tag */
29172ffc8bcaSDan McDonald ddi_put32(acc_handle, &scsi_io_request->CDB.EEDP32.PrimaryReferenceTag,
29182ffc8bcaSDan McDonald BE_32(ref_tag));
29192ffc8bcaSDan McDonald
29202ffc8bcaSDan McDonald ddi_put16(acc_handle,
29212ffc8bcaSDan McDonald &scsi_io_request->CDB.EEDP32.PrimaryApplicationTagMask, 0xffff);
29222ffc8bcaSDan McDonald
29232ffc8bcaSDan McDonald ddi_put32(acc_handle, &scsi_io_request->DataLength,
29242ffc8bcaSDan McDonald ((io_info->numBlocks)*512));
29252ffc8bcaSDan McDonald /* Specify 32-byte cdb */
29262ffc8bcaSDan McDonald ddi_put16(acc_handle, &scsi_io_request->IoFlags, 32);
29272ffc8bcaSDan McDonald
29282ffc8bcaSDan McDonald /* Transfer length */
29292ffc8bcaSDan McDonald cdb[28] = (U8)(((io_info->numBlocks) >> 24) & 0xff);
29302ffc8bcaSDan McDonald cdb[29] = (U8)(((io_info->numBlocks) >> 16) & 0xff);
29312ffc8bcaSDan McDonald cdb[30] = (U8)(((io_info->numBlocks) >> 8) & 0xff);
29322ffc8bcaSDan McDonald cdb[31] = (U8)((io_info->numBlocks) & 0xff);
29332ffc8bcaSDan McDonald
29342ffc8bcaSDan McDonald /* set SCSI IO EEDPFlags */
29352ffc8bcaSDan McDonald EEDPFlags = ddi_get16(acc_handle, &scsi_io_request->EEDPFlags);
29362ffc8bcaSDan McDonald Control = ddi_get32(acc_handle, &scsi_io_request->Control);
29372ffc8bcaSDan McDonald
29382ffc8bcaSDan McDonald /* set SCSI IO EEDPFlags bits */
29392ffc8bcaSDan McDonald if (io_info->isRead) {
29402ffc8bcaSDan McDonald /*
29412ffc8bcaSDan McDonald * For READ commands, the EEDPFlags shall be set to specify to
29422ffc8bcaSDan McDonald * Increment the Primary Reference Tag, to Check the Reference
29432ffc8bcaSDan McDonald * Tag, and to Check and Remove the Protection Information
29442ffc8bcaSDan McDonald * fields.
29452ffc8bcaSDan McDonald */
29462ffc8bcaSDan McDonald EEDPFlags = MPI2_SCSIIO_EEDPFLAGS_INC_PRI_REFTAG |
29472ffc8bcaSDan McDonald MPI2_SCSIIO_EEDPFLAGS_CHECK_REFTAG |
29482ffc8bcaSDan McDonald MPI2_SCSIIO_EEDPFLAGS_CHECK_REMOVE_OP |
29492ffc8bcaSDan McDonald MPI2_SCSIIO_EEDPFLAGS_CHECK_APPTAG |
29502ffc8bcaSDan McDonald MPI2_SCSIIO_EEDPFLAGS_CHECK_GUARD;
29512ffc8bcaSDan McDonald } else {
29522ffc8bcaSDan McDonald /*
29532ffc8bcaSDan McDonald * For WRITE commands, the EEDPFlags shall be set to specify to
29542ffc8bcaSDan McDonald * Increment the Primary Reference Tag, and to Insert
29552ffc8bcaSDan McDonald * Protection Information fields.
29562ffc8bcaSDan McDonald */
29572ffc8bcaSDan McDonald EEDPFlags = MPI2_SCSIIO_EEDPFLAGS_INC_PRI_REFTAG |
29582ffc8bcaSDan McDonald MPI2_SCSIIO_EEDPFLAGS_INSERT_OP;
29592ffc8bcaSDan McDonald }
29602ffc8bcaSDan McDonald Control |= (0x4 << 26);
29612ffc8bcaSDan McDonald
29622ffc8bcaSDan McDonald ddi_put16(acc_handle, &scsi_io_request->EEDPFlags, EEDPFlags);
29632ffc8bcaSDan McDonald ddi_put32(acc_handle, &scsi_io_request->Control, Control);
29642ffc8bcaSDan McDonald ddi_put32(acc_handle,
29652ffc8bcaSDan McDonald &scsi_io_request->EEDPBlockSize, MRSAS_EEDPBLOCKSIZE);
29662ffc8bcaSDan McDonald }
29672ffc8bcaSDan McDonald
29682ffc8bcaSDan McDonald
29692ffc8bcaSDan McDonald /*
29702ffc8bcaSDan McDonald * mrsas_tbolt_set_pd_lba - Sets PD LBA
29712ffc8bcaSDan McDonald * @cdb: CDB
29723344ffb7SToomas Soome * @cdb_size: CDB size
29733344ffb7SToomas Soome * @cdb_len_ptr: cdb length
29742ffc8bcaSDan McDonald * @start_blk: Start block of IO
29753344ffb7SToomas Soome * @num_blocks: Number of blocks
29762ffc8bcaSDan McDonald *
29772ffc8bcaSDan McDonald * Used to set the PD LBA in CDB for FP IOs
29782ffc8bcaSDan McDonald */
29792ffc8bcaSDan McDonald static void
mrsas_tbolt_set_pd_lba(U8 * cdb,size_t cdb_size,uint8_t * cdb_len_ptr,U64 start_blk,U32 num_blocks)29803344ffb7SToomas Soome mrsas_tbolt_set_pd_lba(U8 *cdb, size_t cdb_size, uint8_t *cdb_len_ptr,
29813344ffb7SToomas Soome U64 start_blk, U32 num_blocks)
29822ffc8bcaSDan McDonald {
29832ffc8bcaSDan McDonald U8 cdb_len = *cdb_len_ptr;
29842ffc8bcaSDan McDonald U8 flagvals = 0, opcode = 0, groupnum = 0, control = 0;
29852ffc8bcaSDan McDonald
29862ffc8bcaSDan McDonald /* Some drives don't support 16/12 byte CDB's, convert to 10 */
29872ffc8bcaSDan McDonald if (((cdb_len == 12) || (cdb_len == 16)) &&
29882ffc8bcaSDan McDonald (start_blk <= 0xffffffff)) {
29892ffc8bcaSDan McDonald if (cdb_len == 16) {
29902ffc8bcaSDan McDonald con_log(CL_ANN,
29912ffc8bcaSDan McDonald (CE_NOTE, "Converting READ/WRITE(16) to READ10"));
29922ffc8bcaSDan McDonald opcode = cdb[0] == READ_16 ? READ_10 : WRITE_10;
29932ffc8bcaSDan McDonald flagvals = cdb[1];
29942ffc8bcaSDan McDonald groupnum = cdb[14];
29952ffc8bcaSDan McDonald control = cdb[15];
29962ffc8bcaSDan McDonald } else {
29972ffc8bcaSDan McDonald con_log(CL_ANN,
29982ffc8bcaSDan McDonald (CE_NOTE, "Converting READ/WRITE(12) to READ10"));
29992ffc8bcaSDan McDonald opcode = cdb[0] == READ_12 ? READ_10 : WRITE_10;
30002ffc8bcaSDan McDonald flagvals = cdb[1];
30012ffc8bcaSDan McDonald groupnum = cdb[10];
30022ffc8bcaSDan McDonald control = cdb[11];
30032ffc8bcaSDan McDonald }
30042ffc8bcaSDan McDonald
30053344ffb7SToomas Soome bzero(cdb, cdb_size);
30062ffc8bcaSDan McDonald
30072ffc8bcaSDan McDonald cdb[0] = opcode;
30082ffc8bcaSDan McDonald cdb[1] = flagvals;
30092ffc8bcaSDan McDonald cdb[6] = groupnum;
30102ffc8bcaSDan McDonald cdb[9] = control;
30112ffc8bcaSDan McDonald /* Set transfer length */
30122ffc8bcaSDan McDonald cdb[8] = (U8)(num_blocks & 0xff);
30132ffc8bcaSDan McDonald cdb[7] = (U8)((num_blocks >> 8) & 0xff);
30142ffc8bcaSDan McDonald cdb_len = 10;
30152ffc8bcaSDan McDonald } else if ((cdb_len < 16) && (start_blk > 0xffffffff)) {
30162ffc8bcaSDan McDonald /* Convert to 16 byte CDB for large LBA's */
30172ffc8bcaSDan McDonald con_log(CL_ANN,
30182ffc8bcaSDan McDonald (CE_NOTE, "Converting 6/10/12 CDB to 16 byte CDB"));
30192ffc8bcaSDan McDonald switch (cdb_len) {
30202ffc8bcaSDan McDonald case 6:
30212ffc8bcaSDan McDonald opcode = cdb[0] == READ_6 ? READ_16 : WRITE_16;
30222ffc8bcaSDan McDonald control = cdb[5];
30232ffc8bcaSDan McDonald break;
30242ffc8bcaSDan McDonald case 10:
30252ffc8bcaSDan McDonald opcode = cdb[0] == READ_10 ? READ_16 : WRITE_16;
30262ffc8bcaSDan McDonald flagvals = cdb[1];
30272ffc8bcaSDan McDonald groupnum = cdb[6];
30282ffc8bcaSDan McDonald control = cdb[9];
30292ffc8bcaSDan McDonald break;
30302ffc8bcaSDan McDonald case 12:
30312ffc8bcaSDan McDonald opcode = cdb[0] == READ_12 ? READ_16 : WRITE_16;
30322ffc8bcaSDan McDonald flagvals = cdb[1];
30332ffc8bcaSDan McDonald groupnum = cdb[10];
30342ffc8bcaSDan McDonald control = cdb[11];
30352ffc8bcaSDan McDonald break;
30362ffc8bcaSDan McDonald }
30372ffc8bcaSDan McDonald
30383344ffb7SToomas Soome bzero(cdb, cdb_size);
30392ffc8bcaSDan McDonald
30402ffc8bcaSDan McDonald cdb[0] = opcode;
30412ffc8bcaSDan McDonald cdb[1] = flagvals;
30422ffc8bcaSDan McDonald cdb[14] = groupnum;
30432ffc8bcaSDan McDonald cdb[15] = control;
30442ffc8bcaSDan McDonald
30452ffc8bcaSDan McDonald /* Transfer length */
30462ffc8bcaSDan McDonald cdb[13] = (U8)(num_blocks & 0xff);
30472ffc8bcaSDan McDonald cdb[12] = (U8)((num_blocks >> 8) & 0xff);
30482ffc8bcaSDan McDonald cdb[11] = (U8)((num_blocks >> 16) & 0xff);
30492ffc8bcaSDan McDonald cdb[10] = (U8)((num_blocks >> 24) & 0xff);
30502ffc8bcaSDan McDonald
30512ffc8bcaSDan McDonald /* Specify 16-byte cdb */
30522ffc8bcaSDan McDonald cdb_len = 16;
30532ffc8bcaSDan McDonald } else if ((cdb_len == 6) && (start_blk > 0x1fffff)) {
30542ffc8bcaSDan McDonald /* convert to 10 byte CDB */
30552ffc8bcaSDan McDonald opcode = cdb[0] == READ_6 ? READ_10 : WRITE_10;
30562ffc8bcaSDan McDonald control = cdb[5];
30572ffc8bcaSDan McDonald
30583344ffb7SToomas Soome bzero(cdb, cdb_size);
30592ffc8bcaSDan McDonald cdb[0] = opcode;
30602ffc8bcaSDan McDonald cdb[9] = control;
30612ffc8bcaSDan McDonald
30622ffc8bcaSDan McDonald /* Set transfer length */
30632ffc8bcaSDan McDonald cdb[8] = (U8)(num_blocks & 0xff);
30642ffc8bcaSDan McDonald cdb[7] = (U8)((num_blocks >> 8) & 0xff);
30652ffc8bcaSDan McDonald
30662ffc8bcaSDan McDonald /* Specify 10-byte cdb */
30672ffc8bcaSDan McDonald cdb_len = 10;
30682ffc8bcaSDan McDonald }
30692ffc8bcaSDan McDonald
30702ffc8bcaSDan McDonald
30712ffc8bcaSDan McDonald /* Fall through Normal case, just load LBA here */
30722ffc8bcaSDan McDonald switch (cdb_len) {
30732ffc8bcaSDan McDonald case 6:
30742ffc8bcaSDan McDonald {
30752ffc8bcaSDan McDonald U8 val = cdb[1] & 0xE0;
30762ffc8bcaSDan McDonald cdb[3] = (U8)(start_blk & 0xff);
30772ffc8bcaSDan McDonald cdb[2] = (U8)((start_blk >> 8) & 0xff);
30782ffc8bcaSDan McDonald cdb[1] = val | ((U8)(start_blk >> 16) & 0x1f);
30792ffc8bcaSDan McDonald break;
30802ffc8bcaSDan McDonald }
30812ffc8bcaSDan McDonald case 10:
30822ffc8bcaSDan McDonald cdb[5] = (U8)(start_blk & 0xff);
30832ffc8bcaSDan McDonald cdb[4] = (U8)((start_blk >> 8) & 0xff);
30842ffc8bcaSDan McDonald cdb[3] = (U8)((start_blk >> 16) & 0xff);
30852ffc8bcaSDan McDonald cdb[2] = (U8)((start_blk >> 24) & 0xff);
30862ffc8bcaSDan McDonald break;
30872ffc8bcaSDan McDonald case 12:
30882ffc8bcaSDan McDonald cdb[5] = (U8)(start_blk & 0xff);
30892ffc8bcaSDan McDonald cdb[4] = (U8)((start_blk >> 8) & 0xff);
30902ffc8bcaSDan McDonald cdb[3] = (U8)((start_blk >> 16) & 0xff);
30912ffc8bcaSDan McDonald cdb[2] = (U8)((start_blk >> 24) & 0xff);
30922ffc8bcaSDan McDonald break;
30932ffc8bcaSDan McDonald
30942ffc8bcaSDan McDonald case 16:
30952ffc8bcaSDan McDonald cdb[9] = (U8)(start_blk & 0xff);
30962ffc8bcaSDan McDonald cdb[8] = (U8)((start_blk >> 8) & 0xff);
30972ffc8bcaSDan McDonald cdb[7] = (U8)((start_blk >> 16) & 0xff);
30982ffc8bcaSDan McDonald cdb[6] = (U8)((start_blk >> 24) & 0xff);
30992ffc8bcaSDan McDonald cdb[5] = (U8)((start_blk >> 32) & 0xff);
31002ffc8bcaSDan McDonald cdb[4] = (U8)((start_blk >> 40) & 0xff);
31012ffc8bcaSDan McDonald cdb[3] = (U8)((start_blk >> 48) & 0xff);
31022ffc8bcaSDan McDonald cdb[2] = (U8)((start_blk >> 56) & 0xff);
31032ffc8bcaSDan McDonald break;
31042ffc8bcaSDan McDonald }
31052ffc8bcaSDan McDonald
31062ffc8bcaSDan McDonald *cdb_len_ptr = cdb_len;
31072ffc8bcaSDan McDonald }
31082ffc8bcaSDan McDonald
31092ffc8bcaSDan McDonald
31102ffc8bcaSDan McDonald static int
mrsas_tbolt_check_map_info(struct mrsas_instance * instance)31112ffc8bcaSDan McDonald mrsas_tbolt_check_map_info(struct mrsas_instance *instance)
31122ffc8bcaSDan McDonald {
31132ffc8bcaSDan McDonald MR_FW_RAID_MAP_ALL *ld_map;
31142ffc8bcaSDan McDonald
31152ffc8bcaSDan McDonald if (!mrsas_tbolt_get_ld_map_info(instance)) {
31162ffc8bcaSDan McDonald
3117e65bc174SAndy Fiddaman ld_map = instance->ld_map[instance->map_id & 1];
31182ffc8bcaSDan McDonald
31192ffc8bcaSDan McDonald con_log(CL_ANN1, (CE_NOTE, "ldCount=%d, map size=%d",
31202ffc8bcaSDan McDonald ld_map->raidMap.ldCount, ld_map->raidMap.totalSize));
31212ffc8bcaSDan McDonald
3122e65bc174SAndy Fiddaman if (MR_ValidateMapInfo(
3123e65bc174SAndy Fiddaman instance->ld_map[instance->map_id & 1],
3124e65bc174SAndy Fiddaman instance->load_balance_info)) {
31252ffc8bcaSDan McDonald con_log(CL_ANN,
31262ffc8bcaSDan McDonald (CE_CONT, "MR_ValidateMapInfo success"));
31272ffc8bcaSDan McDonald
31282ffc8bcaSDan McDonald instance->fast_path_io = 1;
31292ffc8bcaSDan McDonald con_log(CL_ANN,
31302ffc8bcaSDan McDonald (CE_NOTE, "instance->fast_path_io %d",
31312ffc8bcaSDan McDonald instance->fast_path_io));
31322ffc8bcaSDan McDonald
31332ffc8bcaSDan McDonald return (DDI_SUCCESS);
31342ffc8bcaSDan McDonald }
31352ffc8bcaSDan McDonald
31362ffc8bcaSDan McDonald }
31372ffc8bcaSDan McDonald
31382ffc8bcaSDan McDonald instance->fast_path_io = 0;
3139ff38cf9dSAndy Fiddaman dev_err(instance->dip, CE_WARN, "MR_ValidateMapInfo failed");
31402ffc8bcaSDan McDonald con_log(CL_ANN, (CE_NOTE,
31412ffc8bcaSDan McDonald "instance->fast_path_io %d", instance->fast_path_io));
31422ffc8bcaSDan McDonald
31432ffc8bcaSDan McDonald return (DDI_FAILURE);
31442ffc8bcaSDan McDonald }
31452ffc8bcaSDan McDonald
31462ffc8bcaSDan McDonald /*
31472ffc8bcaSDan McDonald * Marks HBA as bad. This will be called either when an
31482ffc8bcaSDan McDonald * IO packet times out even after 3 FW resets
31492ffc8bcaSDan McDonald * or FW is found to be fault even after 3 continuous resets.
31502ffc8bcaSDan McDonald */
31512ffc8bcaSDan McDonald
31522ffc8bcaSDan McDonald void
mrsas_tbolt_kill_adapter(struct mrsas_instance * instance)31532ffc8bcaSDan McDonald mrsas_tbolt_kill_adapter(struct mrsas_instance *instance)
31542ffc8bcaSDan McDonald {
3155ff38cf9dSAndy Fiddaman dev_err(instance->dip, CE_NOTE, "TBOLT Kill adapter called");
31562ffc8bcaSDan McDonald
31572ffc8bcaSDan McDonald if (instance->deadadapter == 1)
31582ffc8bcaSDan McDonald return;
31592ffc8bcaSDan McDonald
31602ffc8bcaSDan McDonald con_log(CL_ANN1, (CE_NOTE, "tbolt_kill_adapter: "
31612ffc8bcaSDan McDonald "Writing to doorbell with MFI_STOP_ADP "));
31622ffc8bcaSDan McDonald mutex_enter(&instance->ocr_flags_mtx);
31632ffc8bcaSDan McDonald instance->deadadapter = 1;
31642ffc8bcaSDan McDonald mutex_exit(&instance->ocr_flags_mtx);
31652ffc8bcaSDan McDonald instance->func_ptr->disable_intr(instance);
31662ffc8bcaSDan McDonald WR_RESERVED0_REGISTER(MFI_STOP_ADP, instance);
31672ffc8bcaSDan McDonald /* Flush */
31682ffc8bcaSDan McDonald (void) RD_RESERVED0_REGISTER(instance);
31692ffc8bcaSDan McDonald
31702ffc8bcaSDan McDonald (void) mrsas_print_pending_cmds(instance);
31712ffc8bcaSDan McDonald (void) mrsas_complete_pending_cmds(instance);
31722ffc8bcaSDan McDonald }
31732ffc8bcaSDan McDonald
31742ffc8bcaSDan McDonald void
mrsas_reset_reply_desc(struct mrsas_instance * instance)31752ffc8bcaSDan McDonald mrsas_reset_reply_desc(struct mrsas_instance *instance)
31762ffc8bcaSDan McDonald {
31772ffc8bcaSDan McDonald int i;
31782ffc8bcaSDan McDonald MPI2_REPLY_DESCRIPTORS_UNION *reply_desc;
31792ffc8bcaSDan McDonald instance->reply_read_index = 0;
31802ffc8bcaSDan McDonald
31812ffc8bcaSDan McDonald /* initializing reply address to 0xFFFFFFFF */
31822ffc8bcaSDan McDonald reply_desc = instance->reply_frame_pool;
31832ffc8bcaSDan McDonald
31842ffc8bcaSDan McDonald for (i = 0; i < instance->reply_q_depth; i++) {
31852ffc8bcaSDan McDonald reply_desc->Words = (uint64_t)~0;
31862ffc8bcaSDan McDonald reply_desc++;
31872ffc8bcaSDan McDonald }
31882ffc8bcaSDan McDonald }
31892ffc8bcaSDan McDonald
31902ffc8bcaSDan McDonald int
mrsas_tbolt_reset_ppc(struct mrsas_instance * instance)31912ffc8bcaSDan McDonald mrsas_tbolt_reset_ppc(struct mrsas_instance *instance)
31922ffc8bcaSDan McDonald {
31932ffc8bcaSDan McDonald uint32_t status = 0x00;
31942ffc8bcaSDan McDonald uint32_t retry = 0;
31952ffc8bcaSDan McDonald uint32_t cur_abs_reg_val;
31962ffc8bcaSDan McDonald uint32_t fw_state;
31972ffc8bcaSDan McDonald uint32_t abs_state;
31982ffc8bcaSDan McDonald uint32_t i;
31992ffc8bcaSDan McDonald
32002ffc8bcaSDan McDonald if (instance->deadadapter == 1) {
3201ff38cf9dSAndy Fiddaman dev_err(instance->dip, CE_WARN, "mrsas_tbolt_reset_ppc: "
32022ffc8bcaSDan McDonald "no more resets as HBA has been marked dead");
32032ffc8bcaSDan McDonald return (DDI_FAILURE);
32042ffc8bcaSDan McDonald }
32052ffc8bcaSDan McDonald
32062ffc8bcaSDan McDonald mutex_enter(&instance->ocr_flags_mtx);
32072ffc8bcaSDan McDonald instance->adapterresetinprogress = 1;
32082ffc8bcaSDan McDonald mutex_exit(&instance->ocr_flags_mtx);
32092ffc8bcaSDan McDonald
32102ffc8bcaSDan McDonald instance->func_ptr->disable_intr(instance);
32112ffc8bcaSDan McDonald
32122ffc8bcaSDan McDonald /* Add delay in order to complete the ioctl & io cmds in-flight */
3213eef6dbdfSAndy Fiddaman for (i = 0; i < 3000; i++)
32142ffc8bcaSDan McDonald drv_usecwait(MILLISEC); /* wait for 1000 usecs */
32152ffc8bcaSDan McDonald
32162ffc8bcaSDan McDonald instance->reply_read_index = 0;
32172ffc8bcaSDan McDonald
32182ffc8bcaSDan McDonald retry_reset:
3219eef6dbdfSAndy Fiddaman con_log(CL_ANN, (CE_NOTE, "mrsas_tbolt_reset_ppc: Resetting TBOLT"));
32202ffc8bcaSDan McDonald
3221eef6dbdfSAndy Fiddaman /* Flush */
3222eef6dbdfSAndy Fiddaman WR_TBOLT_IB_WRITE_SEQ(0x0, instance);
3223eef6dbdfSAndy Fiddaman /* Write magic number */
32242ffc8bcaSDan McDonald WR_TBOLT_IB_WRITE_SEQ(0xF, instance);
3225eef6dbdfSAndy Fiddaman WR_TBOLT_IB_WRITE_SEQ(0x4, instance);
32262ffc8bcaSDan McDonald WR_TBOLT_IB_WRITE_SEQ(0xb, instance);
3227eef6dbdfSAndy Fiddaman WR_TBOLT_IB_WRITE_SEQ(0x2, instance);
3228eef6dbdfSAndy Fiddaman WR_TBOLT_IB_WRITE_SEQ(0x7, instance);
32292ffc8bcaSDan McDonald WR_TBOLT_IB_WRITE_SEQ(0xd, instance);
3230eef6dbdfSAndy Fiddaman
32312ffc8bcaSDan McDonald con_log(CL_ANN1, (CE_NOTE,
32322ffc8bcaSDan McDonald "mrsas_tbolt_reset_ppc: magic number written "
32332ffc8bcaSDan McDonald "to write sequence register"));
32342ffc8bcaSDan McDonald
3235eef6dbdfSAndy Fiddaman /* Wait for the diag write enable (DRWE) bit to be set */
3236eef6dbdfSAndy Fiddaman retry = 0;
3237eef6dbdfSAndy Fiddaman status = RD_TBOLT_HOST_DIAG(instance);
3238eef6dbdfSAndy Fiddaman while (!(status & DIAG_WRITE_ENABLE)) {
32392ffc8bcaSDan McDonald delay(100 * drv_usectohz(MILLISEC));
32402ffc8bcaSDan McDonald status = RD_TBOLT_HOST_DIAG(instance);
3241eef6dbdfSAndy Fiddaman if (retry++ >= 100) {
3242ff38cf9dSAndy Fiddaman dev_err(instance->dip, CE_WARN,
3243eef6dbdfSAndy Fiddaman "%s(): timeout waiting for DRWE.", __func__);
32442ffc8bcaSDan McDonald return (DDI_FAILURE);
32452ffc8bcaSDan McDonald }
32462ffc8bcaSDan McDonald }
32472ffc8bcaSDan McDonald
3248eef6dbdfSAndy Fiddaman /* Send reset command */
32492ffc8bcaSDan McDonald WR_TBOLT_HOST_DIAG(status | DIAG_TBOLT_RESET_ADAPTER, instance);
32502ffc8bcaSDan McDonald delay(100 * drv_usectohz(MILLISEC));
32512ffc8bcaSDan McDonald
3252eef6dbdfSAndy Fiddaman /* Wait for reset bit to clear */
3253eef6dbdfSAndy Fiddaman retry = 0;
3254eef6dbdfSAndy Fiddaman status = RD_TBOLT_HOST_DIAG(instance);
32552ffc8bcaSDan McDonald while ((status & DIAG_TBOLT_RESET_ADAPTER)) {
32562ffc8bcaSDan McDonald delay(100 * drv_usectohz(MILLISEC));
3257eef6dbdfSAndy Fiddaman status = RD_TBOLT_HOST_DIAG(instance);
32582ffc8bcaSDan McDonald if (retry++ == 100) {
32592ffc8bcaSDan McDonald /* Dont call kill adapter here */
32602ffc8bcaSDan McDonald /* RESET BIT ADAPTER is cleared by firmare */
32612ffc8bcaSDan McDonald /* mrsas_tbolt_kill_adapter(instance); */
3262ff38cf9dSAndy Fiddaman dev_err(instance->dip, CE_WARN,
3263ff38cf9dSAndy Fiddaman "%s(): RESET FAILED; return failure!!!", __func__);
32642ffc8bcaSDan McDonald return (DDI_FAILURE);
32652ffc8bcaSDan McDonald }
32662ffc8bcaSDan McDonald }
32672ffc8bcaSDan McDonald
32682ffc8bcaSDan McDonald con_log(CL_ANN,
32692ffc8bcaSDan McDonald (CE_NOTE, "mrsas_tbolt_reset_ppc: Adapter reset complete"));
32702ffc8bcaSDan McDonald
32712ffc8bcaSDan McDonald abs_state = instance->func_ptr->read_fw_status_reg(instance);
32722ffc8bcaSDan McDonald retry = 0;
32732ffc8bcaSDan McDonald while ((abs_state <= MFI_STATE_FW_INIT) && (retry++ < 1000)) {
32742ffc8bcaSDan McDonald delay(100 * drv_usectohz(MILLISEC));
32752ffc8bcaSDan McDonald abs_state = instance->func_ptr->read_fw_status_reg(instance);
32762ffc8bcaSDan McDonald }
32772ffc8bcaSDan McDonald if (abs_state <= MFI_STATE_FW_INIT) {
3278ff38cf9dSAndy Fiddaman dev_err(instance->dip, CE_WARN,
32792ffc8bcaSDan McDonald "mrsas_tbolt_reset_ppc: firmware state < MFI_STATE_FW_INIT"
32802ffc8bcaSDan McDonald "state = 0x%x, RETRY RESET.", abs_state);
32812ffc8bcaSDan McDonald goto retry_reset;
32822ffc8bcaSDan McDonald }
32832ffc8bcaSDan McDonald
32842ffc8bcaSDan McDonald /* Mark HBA as bad, if FW is fault after 3 continuous resets */
32852ffc8bcaSDan McDonald if (mfi_state_transition_to_ready(instance) ||
3286eef6dbdfSAndy Fiddaman mrsas_debug_tbolt_fw_faults_after_ocr == 1) {
32872ffc8bcaSDan McDonald cur_abs_reg_val =
32882ffc8bcaSDan McDonald instance->func_ptr->read_fw_status_reg(instance);
32892ffc8bcaSDan McDonald fw_state = cur_abs_reg_val & MFI_STATE_MASK;
32902ffc8bcaSDan McDonald
32912ffc8bcaSDan McDonald con_log(CL_ANN1, (CE_NOTE,
32922ffc8bcaSDan McDonald "mrsas_tbolt_reset_ppc :before fake: FW is not ready "
32932ffc8bcaSDan McDonald "FW state = 0x%x", fw_state));
3294eef6dbdfSAndy Fiddaman if (mrsas_debug_tbolt_fw_faults_after_ocr == 1)
32952ffc8bcaSDan McDonald fw_state = MFI_STATE_FAULT;
32962ffc8bcaSDan McDonald
32972ffc8bcaSDan McDonald con_log(CL_ANN,
32982ffc8bcaSDan McDonald (CE_NOTE, "mrsas_tbolt_reset_ppc : FW is not ready "
32992ffc8bcaSDan McDonald "FW state = 0x%x", fw_state));
33002ffc8bcaSDan McDonald
33012ffc8bcaSDan McDonald if (fw_state == MFI_STATE_FAULT) {
33022ffc8bcaSDan McDonald /* increment the count */
33032ffc8bcaSDan McDonald instance->fw_fault_count_after_ocr++;
33042ffc8bcaSDan McDonald if (instance->fw_fault_count_after_ocr
33052ffc8bcaSDan McDonald < MAX_FW_RESET_COUNT) {
3306ff38cf9dSAndy Fiddaman dev_err(instance->dip, CE_WARN,
3307ff38cf9dSAndy Fiddaman "mrsas_tbolt_reset_ppc: "
33082ffc8bcaSDan McDonald "FW is in fault after OCR count %d "
33092ffc8bcaSDan McDonald "Retry Reset",
33102ffc8bcaSDan McDonald instance->fw_fault_count_after_ocr);
33112ffc8bcaSDan McDonald goto retry_reset;
33122ffc8bcaSDan McDonald
33132ffc8bcaSDan McDonald } else {
3314ff38cf9dSAndy Fiddaman dev_err(instance->dip, CE_WARN, "%s:"
33152ffc8bcaSDan McDonald "Max Reset Count exceeded >%d"
33162ffc8bcaSDan McDonald "Mark HBA as bad, KILL adapter",
3317ff38cf9dSAndy Fiddaman __func__, MAX_FW_RESET_COUNT);
33182ffc8bcaSDan McDonald
33192ffc8bcaSDan McDonald mrsas_tbolt_kill_adapter(instance);
33202ffc8bcaSDan McDonald return (DDI_FAILURE);
33212ffc8bcaSDan McDonald }
33222ffc8bcaSDan McDonald }
33232ffc8bcaSDan McDonald }
33242ffc8bcaSDan McDonald
33252ffc8bcaSDan McDonald /* reset the counter as FW is up after OCR */
33262ffc8bcaSDan McDonald instance->fw_fault_count_after_ocr = 0;
33272ffc8bcaSDan McDonald
33282ffc8bcaSDan McDonald mrsas_reset_reply_desc(instance);
33292ffc8bcaSDan McDonald
33302ffc8bcaSDan McDonald abs_state = mrsas_issue_init_mpi2(instance);
33312ffc8bcaSDan McDonald if (abs_state == (uint32_t)DDI_FAILURE) {
3332ff38cf9dSAndy Fiddaman dev_err(instance->dip, CE_WARN, "mrsas_tbolt_reset_ppc: "
33332ffc8bcaSDan McDonald "INIT failed Retrying Reset");
33342ffc8bcaSDan McDonald goto retry_reset;
33352ffc8bcaSDan McDonald }
33362ffc8bcaSDan McDonald
33372ffc8bcaSDan McDonald (void) mrsas_print_pending_cmds(instance);
33382ffc8bcaSDan McDonald
33392ffc8bcaSDan McDonald instance->func_ptr->enable_intr(instance);
33402ffc8bcaSDan McDonald instance->fw_outstanding = 0;
33412ffc8bcaSDan McDonald
33422ffc8bcaSDan McDonald (void) mrsas_issue_pending_cmds(instance);
33432ffc8bcaSDan McDonald
33442ffc8bcaSDan McDonald instance->aen_cmd->retry_count_for_ocr = 0;
33452ffc8bcaSDan McDonald instance->aen_cmd->drv_pkt_time = 0;
33462ffc8bcaSDan McDonald
33472ffc8bcaSDan McDonald instance->func_ptr->issue_cmd(instance->aen_cmd, instance);
33482ffc8bcaSDan McDonald
33492ffc8bcaSDan McDonald mutex_enter(&instance->ocr_flags_mtx);
33502ffc8bcaSDan McDonald instance->adapterresetinprogress = 0;
33512ffc8bcaSDan McDonald mutex_exit(&instance->ocr_flags_mtx);
33522ffc8bcaSDan McDonald
3353eef6dbdfSAndy Fiddaman dev_err(instance->dip, CE_NOTE, "TBOLT adapter reset successfully");
3354eef6dbdfSAndy Fiddaman
33552ffc8bcaSDan McDonald return (DDI_SUCCESS);
33562ffc8bcaSDan McDonald }
33572ffc8bcaSDan McDonald
33582ffc8bcaSDan McDonald /*
33592ffc8bcaSDan McDonald * mrsas_sync_map_info - Returns FW's ld_map structure
33602ffc8bcaSDan McDonald * @instance: Adapter soft state
33612ffc8bcaSDan McDonald *
33622ffc8bcaSDan McDonald * Issues an internal command (DCMD) to get the FW's controller PD
33632ffc8bcaSDan McDonald * list structure. This information is mainly used to find out SYSTEM
33642ffc8bcaSDan McDonald * supported by the FW.
33652ffc8bcaSDan McDonald */
33662ffc8bcaSDan McDonald
33672ffc8bcaSDan McDonald static int
mrsas_tbolt_sync_map_info(struct mrsas_instance * instance)33682ffc8bcaSDan McDonald mrsas_tbolt_sync_map_info(struct mrsas_instance *instance)
33692ffc8bcaSDan McDonald {
33702ffc8bcaSDan McDonald int ret = 0, i;
33712ffc8bcaSDan McDonald struct mrsas_cmd *cmd = NULL;
33722ffc8bcaSDan McDonald struct mrsas_dcmd_frame *dcmd;
33732ffc8bcaSDan McDonald uint32_t size_sync_info, num_lds;
33742ffc8bcaSDan McDonald LD_TARGET_SYNC *ci = NULL;
33752ffc8bcaSDan McDonald MR_FW_RAID_MAP_ALL *map;
33762ffc8bcaSDan McDonald MR_LD_RAID *raid;
33772ffc8bcaSDan McDonald LD_TARGET_SYNC *ld_sync;
33782ffc8bcaSDan McDonald uint32_t ci_h = 0;
33792ffc8bcaSDan McDonald uint32_t size_map_info;
33802ffc8bcaSDan McDonald
33812ffc8bcaSDan McDonald cmd = get_raid_msg_pkt(instance);
33822ffc8bcaSDan McDonald
33832ffc8bcaSDan McDonald if (cmd == NULL) {
3384ff38cf9dSAndy Fiddaman dev_err(instance->dip, CE_WARN,
3385ff38cf9dSAndy Fiddaman "Failed to get a cmd from free-pool in "
33862ffc8bcaSDan McDonald "mrsas_tbolt_sync_map_info().");
33872ffc8bcaSDan McDonald return (DDI_FAILURE);
33882ffc8bcaSDan McDonald }
33892ffc8bcaSDan McDonald
33902ffc8bcaSDan McDonald /* Clear the frame buffer and assign back the context id */
33912ffc8bcaSDan McDonald bzero((char *)&cmd->frame[0], sizeof (union mrsas_frame));
33922ffc8bcaSDan McDonald ddi_put32(cmd->frame_dma_obj.acc_handle, &cmd->frame->hdr.context,
33932ffc8bcaSDan McDonald cmd->index);
33942ffc8bcaSDan McDonald bzero(cmd->scsi_io_request, sizeof (Mpi2RaidSCSIIORequest_t));
33952ffc8bcaSDan McDonald
33962ffc8bcaSDan McDonald
33972ffc8bcaSDan McDonald map = instance->ld_map[instance->map_id & 1];
33982ffc8bcaSDan McDonald
33992ffc8bcaSDan McDonald num_lds = map->raidMap.ldCount;
34002ffc8bcaSDan McDonald
34012ffc8bcaSDan McDonald dcmd = &cmd->frame->dcmd;
34022ffc8bcaSDan McDonald
34032ffc8bcaSDan McDonald size_sync_info = sizeof (LD_TARGET_SYNC) * num_lds;
34042ffc8bcaSDan McDonald
34052ffc8bcaSDan McDonald con_log(CL_ANN, (CE_NOTE, "size_sync_info =0x%x ; ld count = 0x%x",
34062ffc8bcaSDan McDonald size_sync_info, num_lds));
34072ffc8bcaSDan McDonald
34082ffc8bcaSDan McDonald ci = (LD_TARGET_SYNC *)instance->ld_map[(instance->map_id - 1) & 1];
34092ffc8bcaSDan McDonald
34102ffc8bcaSDan McDonald bzero(ci, sizeof (MR_FW_RAID_MAP_ALL));
34112ffc8bcaSDan McDonald ci_h = instance->ld_map_phy[(instance->map_id - 1) & 1];
34122ffc8bcaSDan McDonald
34132ffc8bcaSDan McDonald bzero(dcmd->mbox.b, DCMD_MBOX_SZ);
34142ffc8bcaSDan McDonald
34152ffc8bcaSDan McDonald ld_sync = (LD_TARGET_SYNC *)ci;
34162ffc8bcaSDan McDonald
34172ffc8bcaSDan McDonald for (i = 0; i < num_lds; i++, ld_sync++) {
34182ffc8bcaSDan McDonald raid = MR_LdRaidGet(i, map);
34192ffc8bcaSDan McDonald
34202ffc8bcaSDan McDonald con_log(CL_ANN1,
34212ffc8bcaSDan McDonald (CE_NOTE, "i : 0x%x, Seq Num : 0x%x, Sync Reqd : 0x%x",
34222ffc8bcaSDan McDonald i, raid->seqNum, raid->flags.ldSyncRequired));
34232ffc8bcaSDan McDonald
34242ffc8bcaSDan McDonald ld_sync->ldTargetId = MR_GetLDTgtId(i, map);
34252ffc8bcaSDan McDonald
34262ffc8bcaSDan McDonald con_log(CL_ANN1, (CE_NOTE, "i : 0x%x, tgt : 0x%x",
34272ffc8bcaSDan McDonald i, ld_sync->ldTargetId));
34282ffc8bcaSDan McDonald
34292ffc8bcaSDan McDonald ld_sync->seqNum = raid->seqNum;
34302ffc8bcaSDan McDonald }
34312ffc8bcaSDan McDonald
34322ffc8bcaSDan McDonald
34332ffc8bcaSDan McDonald size_map_info = sizeof (MR_FW_RAID_MAP) +
34342ffc8bcaSDan McDonald (sizeof (MR_LD_SPAN_MAP) * (MAX_LOGICAL_DRIVES - 1));
34352ffc8bcaSDan McDonald
34362ffc8bcaSDan McDonald dcmd->cmd = MFI_CMD_OP_DCMD;
34372ffc8bcaSDan McDonald dcmd->cmd_status = 0xFF;
34382ffc8bcaSDan McDonald dcmd->sge_count = 1;
34392ffc8bcaSDan McDonald dcmd->flags = MFI_FRAME_DIR_WRITE;
34402ffc8bcaSDan McDonald dcmd->timeout = 0;
34412ffc8bcaSDan McDonald dcmd->pad_0 = 0;
34422ffc8bcaSDan McDonald dcmd->data_xfer_len = size_map_info;
34432ffc8bcaSDan McDonald ASSERT(num_lds <= 255);
34442ffc8bcaSDan McDonald dcmd->mbox.b[0] = (U8)num_lds;
34452ffc8bcaSDan McDonald dcmd->mbox.b[1] = 1; /* Pend */
34462ffc8bcaSDan McDonald dcmd->opcode = MR_DCMD_LD_MAP_GET_INFO;
34472ffc8bcaSDan McDonald dcmd->sgl.sge32[0].phys_addr = ci_h;
34482ffc8bcaSDan McDonald dcmd->sgl.sge32[0].length = size_map_info;
34492ffc8bcaSDan McDonald
34502ffc8bcaSDan McDonald
34512ffc8bcaSDan McDonald instance->map_update_cmd = cmd;
34522ffc8bcaSDan McDonald mr_sas_tbolt_build_mfi_cmd(instance, cmd);
34532ffc8bcaSDan McDonald
34542ffc8bcaSDan McDonald instance->func_ptr->issue_cmd(cmd, instance);
34552ffc8bcaSDan McDonald
34562ffc8bcaSDan McDonald instance->unroll.syncCmd = 1;
34572ffc8bcaSDan McDonald con_log(CL_ANN1, (CE_NOTE, "sync cmd issued. [SMID]:%x", cmd->SMID));
34582ffc8bcaSDan McDonald
34592ffc8bcaSDan McDonald return (ret);
34602ffc8bcaSDan McDonald }
34612ffc8bcaSDan McDonald
34622ffc8bcaSDan McDonald /*
34632ffc8bcaSDan McDonald * abort_syncmap_cmd
34642ffc8bcaSDan McDonald */
34652ffc8bcaSDan McDonald int
abort_syncmap_cmd(struct mrsas_instance * instance,struct mrsas_cmd * cmd_to_abort)34662ffc8bcaSDan McDonald abort_syncmap_cmd(struct mrsas_instance *instance,
34672ffc8bcaSDan McDonald struct mrsas_cmd *cmd_to_abort)
34682ffc8bcaSDan McDonald {
34692ffc8bcaSDan McDonald int ret = 0;
34702ffc8bcaSDan McDonald
34712ffc8bcaSDan McDonald struct mrsas_cmd *cmd;
34722ffc8bcaSDan McDonald struct mrsas_abort_frame *abort_fr;
34732ffc8bcaSDan McDonald
34742ffc8bcaSDan McDonald con_log(CL_ANN1, (CE_NOTE, "chkpnt: abort_ldsync:%d", __LINE__));
34752ffc8bcaSDan McDonald
34762ffc8bcaSDan McDonald cmd = get_raid_msg_mfi_pkt(instance);
34772ffc8bcaSDan McDonald
34782ffc8bcaSDan McDonald if (!cmd) {
3479ff38cf9dSAndy Fiddaman dev_err(instance->dip, CE_WARN,
34802ffc8bcaSDan McDonald "Failed to get a cmd from free-pool abort_syncmap_cmd().");
34812ffc8bcaSDan McDonald return (DDI_FAILURE);
34822ffc8bcaSDan McDonald }
34832ffc8bcaSDan McDonald /* Clear the frame buffer and assign back the context id */
34842ffc8bcaSDan McDonald bzero((char *)&cmd->frame[0], sizeof (union mrsas_frame));
34852ffc8bcaSDan McDonald ddi_put32(cmd->frame_dma_obj.acc_handle, &cmd->frame->hdr.context,
34862ffc8bcaSDan McDonald cmd->index);
34872ffc8bcaSDan McDonald
34882ffc8bcaSDan McDonald abort_fr = &cmd->frame->abort;
34892ffc8bcaSDan McDonald
34902ffc8bcaSDan McDonald /* prepare and issue the abort frame */
34912ffc8bcaSDan McDonald ddi_put8(cmd->frame_dma_obj.acc_handle,
34922ffc8bcaSDan McDonald &abort_fr->cmd, MFI_CMD_OP_ABORT);
34932ffc8bcaSDan McDonald ddi_put8(cmd->frame_dma_obj.acc_handle, &abort_fr->cmd_status,
34942ffc8bcaSDan McDonald MFI_CMD_STATUS_SYNC_MODE);
34952ffc8bcaSDan McDonald ddi_put16(cmd->frame_dma_obj.acc_handle, &abort_fr->flags, 0);
34962ffc8bcaSDan McDonald ddi_put32(cmd->frame_dma_obj.acc_handle, &abort_fr->abort_context,
34972ffc8bcaSDan McDonald cmd_to_abort->index);
34982ffc8bcaSDan McDonald ddi_put32(cmd->frame_dma_obj.acc_handle,
34992ffc8bcaSDan McDonald &abort_fr->abort_mfi_phys_addr_lo, cmd_to_abort->frame_phys_addr);
35002ffc8bcaSDan McDonald ddi_put32(cmd->frame_dma_obj.acc_handle,
35012ffc8bcaSDan McDonald &abort_fr->abort_mfi_phys_addr_hi, 0);
35022ffc8bcaSDan McDonald
35032ffc8bcaSDan McDonald cmd->frame_count = 1;
35042ffc8bcaSDan McDonald
35052ffc8bcaSDan McDonald mr_sas_tbolt_build_mfi_cmd(instance, cmd);
35062ffc8bcaSDan McDonald
35072ffc8bcaSDan McDonald if (instance->func_ptr->issue_cmd_in_poll_mode(instance, cmd)) {
35082ffc8bcaSDan McDonald con_log(CL_ANN1, (CE_WARN,
35092ffc8bcaSDan McDonald "abort_ldsync_cmd: issue_cmd_in_poll_mode failed"));
35102ffc8bcaSDan McDonald ret = -1;
35112ffc8bcaSDan McDonald } else {
35122ffc8bcaSDan McDonald ret = 0;
35132ffc8bcaSDan McDonald }
35142ffc8bcaSDan McDonald
35152ffc8bcaSDan McDonald return_raid_msg_mfi_pkt(instance, cmd);
35162ffc8bcaSDan McDonald
35172ffc8bcaSDan McDonald atomic_add_16(&instance->fw_outstanding, (-1));
35182ffc8bcaSDan McDonald
35192ffc8bcaSDan McDonald return (ret);
35202ffc8bcaSDan McDonald }
35212ffc8bcaSDan McDonald
3522a1c36c8bSDan McDonald /*
3523a1c36c8bSDan McDonald * Even though these functions were originally intended for 2208 only, it
3524a1c36c8bSDan McDonald * turns out they're useful for "Skinny" support as well. In a perfect world,
3525a1c36c8bSDan McDonald * these two functions would be either in mr_sas.c, or in their own new source
3526a1c36c8bSDan McDonald * file. Since this driver needs some cleanup anyway, keep this portion in
3527a1c36c8bSDan McDonald * mind as well.
3528a1c36c8bSDan McDonald */
3529a1c36c8bSDan McDonald
35302ffc8bcaSDan McDonald int
mrsas_tbolt_config_pd(struct mrsas_instance * instance,uint16_t tgt,uint8_t lun,dev_info_t ** ldip)35312ffc8bcaSDan McDonald mrsas_tbolt_config_pd(struct mrsas_instance *instance, uint16_t tgt,
35322ffc8bcaSDan McDonald uint8_t lun, dev_info_t **ldip)
35332ffc8bcaSDan McDonald {
35342ffc8bcaSDan McDonald struct scsi_device *sd;
35352ffc8bcaSDan McDonald dev_info_t *child;
35362ffc8bcaSDan McDonald int rval, dtype;
35372ffc8bcaSDan McDonald struct mrsas_tbolt_pd_info *pds = NULL;
35382ffc8bcaSDan McDonald
35392ffc8bcaSDan McDonald con_log(CL_ANN1, (CE_NOTE, "mrsas_tbolt_config_pd: t = %d l = %d",
35402ffc8bcaSDan McDonald tgt, lun));
35412ffc8bcaSDan McDonald
35422ffc8bcaSDan McDonald if ((child = mrsas_find_child(instance, tgt, lun)) != NULL) {
35432ffc8bcaSDan McDonald if (ldip) {
35442ffc8bcaSDan McDonald *ldip = child;
35452ffc8bcaSDan McDonald }
35462ffc8bcaSDan McDonald if (instance->mr_tbolt_pd_list[tgt].flag != MRDRV_TGT_VALID) {
35472ffc8bcaSDan McDonald rval = mrsas_service_evt(instance, tgt, 1,
3548*97ac1f64SToomas Soome MRSAS_EVT_UNCONFIG_TGT, 0);
35492ffc8bcaSDan McDonald con_log(CL_ANN1, (CE_WARN,
35502ffc8bcaSDan McDonald "mr_sas:DELETING STALE ENTRY rval = %d "
35512ffc8bcaSDan McDonald "tgt id = %d", rval, tgt));
35522ffc8bcaSDan McDonald return (NDI_FAILURE);
35532ffc8bcaSDan McDonald }
35542ffc8bcaSDan McDonald return (NDI_SUCCESS);
35552ffc8bcaSDan McDonald }
35562ffc8bcaSDan McDonald
35572ffc8bcaSDan McDonald pds = (struct mrsas_tbolt_pd_info *)
35582ffc8bcaSDan McDonald kmem_zalloc(sizeof (struct mrsas_tbolt_pd_info), KM_SLEEP);
35592ffc8bcaSDan McDonald mrsas_tbolt_get_pd_info(instance, pds, tgt);
35602ffc8bcaSDan McDonald dtype = pds->scsiDevType;
35612ffc8bcaSDan McDonald
35622ffc8bcaSDan McDonald /* Check for Disk */
35632ffc8bcaSDan McDonald if ((dtype == DTYPE_DIRECT)) {
35642ffc8bcaSDan McDonald if ((dtype == DTYPE_DIRECT) &&
35652ffc8bcaSDan McDonald (LE_16(pds->fwState) != PD_SYSTEM)) {
35662ffc8bcaSDan McDonald kmem_free(pds, sizeof (struct mrsas_tbolt_pd_info));
35672ffc8bcaSDan McDonald return (NDI_FAILURE);
35682ffc8bcaSDan McDonald }
35692ffc8bcaSDan McDonald sd = kmem_zalloc(sizeof (struct scsi_device), KM_SLEEP);
35702ffc8bcaSDan McDonald sd->sd_address.a_hba_tran = instance->tran;
35712ffc8bcaSDan McDonald sd->sd_address.a_target = (uint16_t)tgt;
35722ffc8bcaSDan McDonald sd->sd_address.a_lun = (uint8_t)lun;
35732ffc8bcaSDan McDonald
35742ffc8bcaSDan McDonald if (scsi_hba_probe(sd, NULL) == SCSIPROBE_EXISTS) {
35752ffc8bcaSDan McDonald rval = mrsas_config_scsi_device(instance, sd, ldip);
3576ff38cf9dSAndy Fiddaman dev_err(instance->dip, CE_CONT,
3577ff38cf9dSAndy Fiddaman "?Phys. device found: tgt %d dtype %d: %s\n",
3578ff38cf9dSAndy Fiddaman tgt, dtype, sd->sd_inq->inq_vid);
35792ffc8bcaSDan McDonald } else {
35802ffc8bcaSDan McDonald rval = NDI_FAILURE;
35812ffc8bcaSDan McDonald con_log(CL_DLEVEL1, (CE_NOTE, "Phys. device Not found "
35822ffc8bcaSDan McDonald "scsi_hba_probe Failed: tgt %d dtype %d: %s",
35832ffc8bcaSDan McDonald tgt, dtype, sd->sd_inq->inq_vid));
35842ffc8bcaSDan McDonald }
35852ffc8bcaSDan McDonald
35862ffc8bcaSDan McDonald /* sd_unprobe is blank now. Free buffer manually */
35872ffc8bcaSDan McDonald if (sd->sd_inq) {
35882ffc8bcaSDan McDonald kmem_free(sd->sd_inq, SUN_INQSIZE);
35892ffc8bcaSDan McDonald sd->sd_inq = (struct scsi_inquiry *)NULL;
35902ffc8bcaSDan McDonald }
35912ffc8bcaSDan McDonald kmem_free(sd, sizeof (struct scsi_device));
35922ffc8bcaSDan McDonald } else {
35932ffc8bcaSDan McDonald con_log(CL_ANN1, (CE_NOTE,
3594ff38cf9dSAndy Fiddaman "?Device not supported: tgt %d lun %d dtype %d",
35952ffc8bcaSDan McDonald tgt, lun, dtype));
35962ffc8bcaSDan McDonald rval = NDI_FAILURE;
35972ffc8bcaSDan McDonald }
35982ffc8bcaSDan McDonald
35992ffc8bcaSDan McDonald kmem_free(pds, sizeof (struct mrsas_tbolt_pd_info));
36002ffc8bcaSDan McDonald con_log(CL_ANN1, (CE_NOTE, "mrsas_config_pd: return rval = %d",
36012ffc8bcaSDan McDonald rval));
36022ffc8bcaSDan McDonald return (rval);
36032ffc8bcaSDan McDonald }
36042ffc8bcaSDan McDonald
36052ffc8bcaSDan McDonald static void
mrsas_tbolt_get_pd_info(struct mrsas_instance * instance,struct mrsas_tbolt_pd_info * pds,int tgt)36062ffc8bcaSDan McDonald mrsas_tbolt_get_pd_info(struct mrsas_instance *instance,
36072ffc8bcaSDan McDonald struct mrsas_tbolt_pd_info *pds, int tgt)
36082ffc8bcaSDan McDonald {
36092ffc8bcaSDan McDonald struct mrsas_cmd *cmd;
36102ffc8bcaSDan McDonald struct mrsas_dcmd_frame *dcmd;
36112ffc8bcaSDan McDonald dma_obj_t dcmd_dma_obj;
36122ffc8bcaSDan McDonald
3613a1c36c8bSDan McDonald ASSERT(instance->tbolt || instance->skinny);
3614a1c36c8bSDan McDonald
3615a1c36c8bSDan McDonald if (instance->tbolt)
36162ffc8bcaSDan McDonald cmd = get_raid_msg_pkt(instance);
3617a1c36c8bSDan McDonald else
3618a1c36c8bSDan McDonald cmd = mrsas_get_mfi_pkt(instance);
36192ffc8bcaSDan McDonald
36202ffc8bcaSDan McDonald if (!cmd) {
36212ffc8bcaSDan McDonald con_log(CL_ANN1,
36222ffc8bcaSDan McDonald (CE_WARN, "Failed to get a cmd for get pd info"));
36232ffc8bcaSDan McDonald return;
36242ffc8bcaSDan McDonald }
36252ffc8bcaSDan McDonald
36262ffc8bcaSDan McDonald /* Clear the frame buffer and assign back the context id */
36272ffc8bcaSDan McDonald bzero((char *)&cmd->frame[0], sizeof (union mrsas_frame));
36282ffc8bcaSDan McDonald ddi_put32(cmd->frame_dma_obj.acc_handle, &cmd->frame->hdr.context,
36292ffc8bcaSDan McDonald cmd->index);
36302ffc8bcaSDan McDonald
36312ffc8bcaSDan McDonald
36322ffc8bcaSDan McDonald dcmd = &cmd->frame->dcmd;
36332ffc8bcaSDan McDonald dcmd_dma_obj.size = sizeof (struct mrsas_tbolt_pd_info);
36342ffc8bcaSDan McDonald dcmd_dma_obj.dma_attr = mrsas_generic_dma_attr;
36352ffc8bcaSDan McDonald dcmd_dma_obj.dma_attr.dma_attr_addr_hi = 0xffffffff;
36362ffc8bcaSDan McDonald dcmd_dma_obj.dma_attr.dma_attr_count_max = 0xffffffff;
36372ffc8bcaSDan McDonald dcmd_dma_obj.dma_attr.dma_attr_sgllen = 1;
36382ffc8bcaSDan McDonald dcmd_dma_obj.dma_attr.dma_attr_align = 1;
36392ffc8bcaSDan McDonald
36402ffc8bcaSDan McDonald (void) mrsas_alloc_dma_obj(instance, &dcmd_dma_obj,
36412ffc8bcaSDan McDonald DDI_STRUCTURE_LE_ACC);
36422ffc8bcaSDan McDonald bzero(dcmd_dma_obj.buffer, sizeof (struct mrsas_tbolt_pd_info));
36432ffc8bcaSDan McDonald bzero(dcmd->mbox.b, 12);
36442ffc8bcaSDan McDonald ddi_put8(cmd->frame_dma_obj.acc_handle, &dcmd->cmd, MFI_CMD_OP_DCMD);
36452ffc8bcaSDan McDonald ddi_put8(cmd->frame_dma_obj.acc_handle, &dcmd->cmd_status, 0);
36462ffc8bcaSDan McDonald ddi_put8(cmd->frame_dma_obj.acc_handle, &dcmd->sge_count, 1);
36472ffc8bcaSDan McDonald ddi_put16(cmd->frame_dma_obj.acc_handle, &dcmd->flags,
36482ffc8bcaSDan McDonald MFI_FRAME_DIR_READ);
36492ffc8bcaSDan McDonald ddi_put16(cmd->frame_dma_obj.acc_handle, &dcmd->timeout, 0);
36502ffc8bcaSDan McDonald ddi_put32(cmd->frame_dma_obj.acc_handle, &dcmd->data_xfer_len,
36512ffc8bcaSDan McDonald sizeof (struct mrsas_tbolt_pd_info));
36522ffc8bcaSDan McDonald ddi_put32(cmd->frame_dma_obj.acc_handle, &dcmd->opcode,
36532ffc8bcaSDan McDonald MR_DCMD_PD_GET_INFO);
36542ffc8bcaSDan McDonald ddi_put32(cmd->frame_dma_obj.acc_handle, &dcmd->mbox.w[0], tgt);
36552ffc8bcaSDan McDonald ddi_put32(cmd->frame_dma_obj.acc_handle, &dcmd->sgl.sge32[0].length,
36562ffc8bcaSDan McDonald sizeof (struct mrsas_tbolt_pd_info));
36572ffc8bcaSDan McDonald ddi_put32(cmd->frame_dma_obj.acc_handle, &dcmd->sgl.sge32[0].phys_addr,
36582ffc8bcaSDan McDonald dcmd_dma_obj.dma_cookie[0].dmac_address);
36592ffc8bcaSDan McDonald
36602ffc8bcaSDan McDonald cmd->sync_cmd = MRSAS_TRUE;
36612ffc8bcaSDan McDonald cmd->frame_count = 1;
36622ffc8bcaSDan McDonald
3663a1c36c8bSDan McDonald if (instance->tbolt)
36642ffc8bcaSDan McDonald mr_sas_tbolt_build_mfi_cmd(instance, cmd);
36652ffc8bcaSDan McDonald
36662ffc8bcaSDan McDonald instance->func_ptr->issue_cmd_in_sync_mode(instance, cmd);
36672ffc8bcaSDan McDonald
36682ffc8bcaSDan McDonald ddi_rep_get8(cmd->frame_dma_obj.acc_handle, (uint8_t *)pds,
36692ffc8bcaSDan McDonald (uint8_t *)dcmd_dma_obj.buffer, sizeof (struct mrsas_tbolt_pd_info),
36702ffc8bcaSDan McDonald DDI_DEV_AUTOINCR);
36712ffc8bcaSDan McDonald (void) mrsas_free_dma_obj(instance, dcmd_dma_obj);
3672a1c36c8bSDan McDonald
3673a1c36c8bSDan McDonald if (instance->tbolt)
36742ffc8bcaSDan McDonald return_raid_msg_pkt(instance, cmd);
3675a1c36c8bSDan McDonald else
3676a1c36c8bSDan McDonald mrsas_return_mfi_pkt(instance, cmd);
36772ffc8bcaSDan McDonald }
3678