From dc69dfc3bf6431a92f7bb0dc445bbf588e909c3b Mon Sep 17 00:00:00 2001 From: kadesai Date: Fri, 14 Dec 2018 08:03:28 +0000 Subject: [PATCH] This patch will add support for new DCMD to get PD information and a single data structure to specify LD and JBOD. Submitted by: Sumit Saxena Reviewed by: Kashyap Desai Approved by: ken MFC after: 3 days Sponsored by: Broadcom Inc --- sys/dev/mrsas/mrsas.c | 192 +++++++++++++++++++++++++++++++++++++- sys/dev/mrsas/mrsas.h | 212 +++++++++++++++++++++++++++++++++++++++++- 2 files changed, 400 insertions(+), 4 deletions(-) diff --git a/sys/dev/mrsas/mrsas.c b/sys/dev/mrsas/mrsas.c index 700d70589a8e..5861c892f31b 100644 --- a/sys/dev/mrsas/mrsas.c +++ b/sys/dev/mrsas/mrsas.c @@ -90,6 +90,8 @@ static void mrsas_update_ext_vd_details(struct mrsas_softc *sc); static int mrsas_issue_blocked_abort_cmd(struct mrsas_softc *sc, struct mrsas_mfi_cmd *cmd_to_abort); +static void +mrsas_get_pd_info(struct mrsas_softc *sc, u_int16_t device_id); static struct mrsas_softc * mrsas_get_softc_instance(struct cdev *dev, u_long cmd, caddr_t arg); @@ -971,6 +973,7 @@ mrsas_attach(device_t dev) static void mrsas_ich_startup(void *arg) { + int i = 0; struct mrsas_softc *sc = (struct mrsas_softc *)arg; /* @@ -1006,6 +1009,13 @@ mrsas_ich_startup(void *arg) /* Enable Interrupts */ mrsas_enable_intr(sc); + /* Call DCMD get_pd_info for all system PDs */ + for (i = 0; i < MRSAS_MAX_PD; i++) { + if ((sc->target_list[i].target_id != 0xffff) && + sc->pd_info_mem) + mrsas_get_pd_info(sc, sc->target_list[i].target_id); + } + /* Initiate AEN (Asynchronous Event Notification) */ if (mrsas_start_aen(sc)) { device_printf(sc->mrsas_dev, "Error: AEN registration FAILED !!! " @@ -1215,6 +1225,16 @@ mrsas_free_mem(struct mrsas_softc *sc) if (sc->evt_detail_tag != NULL) bus_dma_tag_destroy(sc->evt_detail_tag); + /* + * Free PD info memory + */ + if (sc->pd_info_phys_addr) + bus_dmamap_unload(sc->pd_info_tag, sc->pd_info_dmamap); + if (sc->pd_info_mem != NULL) + bus_dmamem_free(sc->pd_info_tag, sc->pd_info_mem, sc->pd_info_dmamap); + if (sc->pd_info_tag != NULL) + bus_dma_tag_destroy(sc->pd_info_tag); + /* * Free MFI frames */ @@ -1808,7 +1828,7 @@ static int mrsas_alloc_mem(struct mrsas_softc *sc) { u_int32_t verbuf_size, io_req_size, reply_desc_size, sense_size, chain_frame_size, - evt_detail_size, count; + evt_detail_size, count, pd_info_size; /* * Allocate parent DMA tag @@ -2009,6 +2029,38 @@ mrsas_alloc_mem(struct mrsas_softc *sc) device_printf(sc->mrsas_dev, "Cannot load Event detail buffer memory\n"); return (ENOMEM); } + + /* + * Allocate for PD INFO structure + */ + pd_info_size = sizeof(struct mrsas_pd_info); + if (bus_dma_tag_create(sc->mrsas_parent_tag, + 1, 0, + BUS_SPACE_MAXADDR_32BIT, + BUS_SPACE_MAXADDR, + NULL, NULL, + pd_info_size, + 1, + pd_info_size, + BUS_DMA_ALLOCNOW, + NULL, NULL, + &sc->pd_info_tag)) { + device_printf(sc->mrsas_dev, "Cannot create PD INFO tag\n"); + return (ENOMEM); + } + if (bus_dmamem_alloc(sc->pd_info_tag, (void **)&sc->pd_info_mem, + BUS_DMA_NOWAIT, &sc->pd_info_dmamap)) { + device_printf(sc->mrsas_dev, "Cannot alloc PD INFO buffer memory\n"); + return (ENOMEM); + } + bzero(sc->pd_info_mem, pd_info_size); + if (bus_dmamap_load(sc->pd_info_tag, sc->pd_info_dmamap, + sc->pd_info_mem, pd_info_size, mrsas_addr_cb, + &sc->pd_info_phys_addr, BUS_DMA_NOWAIT)) { + device_printf(sc->mrsas_dev, "Cannot load PD INFO buffer memory\n"); + return (ENOMEM); + } + /* * Create a dma tag for data buffers; size will be the maximum * possible I/O size (280kB). @@ -2297,6 +2349,7 @@ mrsas_init_fw(struct mrsas_softc *sc) device_printf(sc->mrsas_dev, "Adapter initialize Fail.\n"); return (1); } + /* Allocate internal commands for pass-thru */ if (mrsas_alloc_mfi_cmds(sc) != SUCCESS) { device_printf(sc->mrsas_dev, "Allocate MFI cmd failed.\n"); @@ -2334,6 +2387,12 @@ mrsas_init_fw(struct mrsas_softc *sc) } megasas_setup_jbod_map(sc); + + memset(sc->target_list, 0, + MRSAS_MAX_TM_TARGETS * sizeof(struct mrsas_target)); + for (i = 0; i < MRSAS_MAX_TM_TARGETS; i++) + sc->target_list[i].target_id = 0xffff; + /* For pass-thru, get PD/LD list and controller info */ memset(sc->pd_list, 0, MRSAS_MAX_PD * sizeof(struct mrsas_pd_list)); @@ -4271,6 +4330,113 @@ mrsas_sync_map_info(struct mrsas_softc *sc) return (retcode); } +/* Input: dcmd.opcode - MR_DCMD_PD_GET_INFO + * dcmd.mbox.s[0] - deviceId for this physical drive + * dcmd.sge IN - ptr to returned MR_PD_INFO structure + * Desc: Firmware return the physical drive info structure + * + */ +static void +mrsas_get_pd_info(struct mrsas_softc *sc, u_int16_t device_id) +{ + int retcode; + u_int8_t do_ocr = 1; + struct mrsas_mfi_cmd *cmd; + struct mrsas_dcmd_frame *dcmd; + + cmd = mrsas_get_mfi_cmd(sc); + + if (!cmd) { + device_printf(sc->mrsas_dev, + "Cannot alloc for get PD info cmd\n"); + return; + } + dcmd = &cmd->frame->dcmd; + + memset(sc->pd_info_mem, 0, sizeof(struct mrsas_pd_info)); + memset(dcmd->mbox.b, 0, MFI_MBOX_SIZE); + + dcmd->mbox.s[0] = device_id; + dcmd->cmd = MFI_CMD_DCMD; + dcmd->cmd_status = 0xFF; + dcmd->sge_count = 1; + dcmd->flags = MFI_FRAME_DIR_READ; + dcmd->timeout = 0; + dcmd->pad_0 = 0; + dcmd->data_xfer_len = sizeof(struct mrsas_pd_info); + dcmd->opcode = MR_DCMD_PD_GET_INFO; + dcmd->sgl.sge32[0].phys_addr = (u_int32_t)sc->pd_info_phys_addr; + dcmd->sgl.sge32[0].length = sizeof(struct mrsas_pd_info); + + if (!sc->mask_interrupts) + retcode = mrsas_issue_blocked_cmd(sc, cmd); + else + retcode = mrsas_issue_polled(sc, cmd); + + if (retcode == ETIMEDOUT) + goto dcmd_timeout; + + sc->target_list[device_id].interface_type = + sc->pd_info_mem->state.ddf.pdType.intf; + + do_ocr = 0; + +dcmd_timeout: + + if (do_ocr) + sc->do_timedout_reset = MFI_DCMD_TIMEOUT_OCR; + + if (!sc->mask_interrupts) + mrsas_release_mfi_cmd(cmd); +} + +/* + * mrsas_add_target: Add target ID of system PD/VD to driver's data structure. + * sc: Adapter's soft state + * target_id: Unique target id per controller(managed by driver) + * for system PDs- target ID ranges from 0 to (MRSAS_MAX_PD - 1) + * for VDs- target ID ranges from MRSAS_MAX_PD to MRSAS_MAX_TM_TARGETS + * return: void + * Descripton: This function will be called whenever system PD or VD is created. + */ +static void mrsas_add_target(struct mrsas_softc *sc, + u_int16_t target_id) +{ + sc->target_list[target_id].target_id = target_id; + + device_printf(sc->mrsas_dev, + "%s created target ID: 0x%x\n", + (target_id < MRSAS_MAX_PD ? "System PD" : "VD"), + (target_id < MRSAS_MAX_PD ? target_id : (target_id - MRSAS_MAX_PD))); + /* + * If interrupts are enabled, then only fire DCMD to get pd_info + * for system PDs + */ + if (!sc->mask_interrupts && sc->pd_info_mem && + (target_id < MRSAS_MAX_PD)) + mrsas_get_pd_info(sc, target_id); + +} + +/* + * mrsas_remove_target: Remove target ID of system PD/VD from driver's data structure. + * sc: Adapter's soft state + * target_id: Unique target id per controller(managed by driver) + * for system PDs- target ID ranges from 0 to (MRSAS_MAX_PD - 1) + * for VDs- target ID ranges from MRSAS_MAX_PD to MRSAS_MAX_TM_TARGETS + * return: void + * Descripton: This function will be called whenever system PD or VD is deleted + */ +static void mrsas_remove_target(struct mrsas_softc *sc, + u_int16_t target_id) +{ + sc->target_list[target_id].target_id = 0xffff; + device_printf(sc->mrsas_dev, + "%s deleted target ID: 0x%x\n", + (target_id < MRSAS_MAX_PD ? "System PD" : "VD"), + (target_id < MRSAS_MAX_PD ? target_id : (target_id - MRSAS_MAX_PD))); +} + /* * mrsas_get_pd_list: Returns FW's PD list structure input: * Adapter soft state @@ -4347,8 +4513,18 @@ mrsas_get_pd_list(struct mrsas_softc *sc) pd_addr->scsiDevType; sc->local_pd_list[pd_addr->deviceId].driveState = MR_PD_STATE_SYSTEM; + if (sc->target_list[pd_addr->deviceId].target_id == 0xffff) + mrsas_add_target(sc, pd_addr->deviceId); pd_addr++; } + for (pd_index = 0; pd_index < MRSAS_MAX_PD; pd_index++) { + if ((sc->local_pd_list[pd_index].driveState != + MR_PD_STATE_SYSTEM) && + (sc->target_list[pd_index].target_id != + 0xffff)) { + mrsas_remove_target(sc, pd_index); + } + } /* * Use mutext/spinlock if pd_list component size increase more than * 32 bit. @@ -4380,7 +4556,7 @@ mrsas_get_pd_list(struct mrsas_softc *sc) static int mrsas_get_ld_list(struct mrsas_softc *sc) { - int ld_list_size, retcode = 0, ld_index = 0, ids = 0; + int ld_list_size, retcode = 0, ld_index = 0, ids = 0, drv_tgt_id; u_int8_t do_ocr = 1; struct mrsas_mfi_cmd *cmd; struct mrsas_dcmd_frame *dcmd; @@ -4442,11 +4618,21 @@ mrsas_get_ld_list(struct mrsas_softc *sc) sc->CurLdCount = ld_list_mem->ldCount; memset(sc->ld_ids, 0xff, MAX_LOGICAL_DRIVES_EXT); for (ld_index = 0; ld_index < ld_list_mem->ldCount; ld_index++) { + ids = ld_list_mem->ldList[ld_index].ref.ld_context.targetId; + drv_tgt_id = ids + MRSAS_MAX_PD; if (ld_list_mem->ldList[ld_index].state != 0) { - ids = ld_list_mem->ldList[ld_index].ref.ld_context.targetId; sc->ld_ids[ids] = ld_list_mem->ldList[ld_index].ref.ld_context.targetId; + if (sc->target_list[drv_tgt_id].target_id == + 0xffff) + mrsas_add_target(sc, drv_tgt_id); + } else { + if (sc->target_list[drv_tgt_id].target_id != + 0xffff) + mrsas_remove_target(sc, + drv_tgt_id); } } + do_ocr = 0; } dcmd_timeout: diff --git a/sys/dev/mrsas/mrsas.h b/sys/dev/mrsas/mrsas.h index a02a0bdbc929..6168a6e03ec1 100644 --- a/sys/dev/mrsas/mrsas.h +++ b/sys/dev/mrsas/mrsas.h @@ -740,6 +740,7 @@ Mpi2IOCInitRequest_t, MPI2_POINTER pMpi2IOCInitRequest_t; #define MR_DCMD_SYSTEM_PD_MAP_GET_INFO 0x0200e102 #define MR_DCMD_PD_MFI_TASK_MGMT 0x0200e100 +#define MR_DCMD_PD_GET_INFO 0x02020000 #define MRSAS_MAX_PD_CHANNELS 1 #define MRSAS_MAX_LD_CHANNELS 1 #define MRSAS_MAX_DEV_PER_CHANNEL 256 @@ -2944,6 +2945,210 @@ typedef struct _MRSAS_DRV_PCI_INFORMATION { u_int8_t reserved2[28]; } MRSAS_DRV_PCI_INFORMATION, *PMRSAS_DRV_PCI_INFORMATION; +typedef enum _MR_PD_TYPE { + UNKNOWN_DRIVE = 0, + PARALLEL_SCSI = 1, + SAS_PD = 2, + SATA_PD = 3, + FC_PD = 4, + NVME_PD = 5, +} MR_PD_TYPE; + +typedef union _MR_PD_REF { + struct { + u_int16_t deviceId; + u_int16_t seqNum; + } mrPdRef; + u_int32_t ref; +} MR_PD_REF; + +/* + * define the DDF Type bit structure + */ +union MR_PD_DDF_TYPE { + struct { + union { + struct { + u_int16_t forcedPDGUID:1; + u_int16_t inVD:1; + u_int16_t isGlobalSpare:1; + u_int16_t isSpare:1; + u_int16_t isForeign:1; + u_int16_t reserved:7; + u_int16_t intf:4; + } pdType; + u_int16_t type; + }; + u_int16_t reserved; + } ddf; + struct { + u_int32_t reserved; + } nonDisk; + u_int32_t type; +} __packed; + +/* + * defines the progress structure + */ +union MR_PROGRESS { + struct { + u_int16_t progress; + union { + u_int16_t elapsedSecs; + u_int16_t elapsedSecsForLastPercent; + }; + } mrProgress; + u_int32_t w; +} __packed; + +/* + * defines the physical drive progress structure + */ +struct MR_PD_PROGRESS { + struct { + u_int32_t rbld:1; + u_int32_t patrol:1; + u_int32_t clear:1; + u_int32_t copyBack:1; + u_int32_t erase:1; + u_int32_t locate:1; + u_int32_t reserved:26; + } active; + union MR_PROGRESS rbld; + union MR_PROGRESS patrol; + union { + union MR_PROGRESS clear; + union MR_PROGRESS erase; + }; + + struct { + u_int32_t rbld:1; + u_int32_t patrol:1; + u_int32_t clear:1; + u_int32_t copyBack:1; + u_int32_t erase:1; + u_int32_t reserved:27; + } pause; + + union MR_PROGRESS reserved[3]; +} __packed; + + +struct mrsas_pd_info { + MR_PD_REF ref; + u_int8_t inquiryData[96]; + u_int8_t vpdPage83[64]; + + u_int8_t notSupported; + u_int8_t scsiDevType; + + union { + u_int8_t connectedPortBitmap; + u_int8_t connectedPortNumbers; + }; + + u_int8_t deviceSpeed; + u_int32_t mediaErrCount; + u_int32_t otherErrCount; + u_int32_t predFailCount; + u_int32_t lastPredFailEventSeqNum; + + u_int16_t fwState; + u_int8_t disabledForRemoval; + u_int8_t linkSpeed; + union MR_PD_DDF_TYPE state; + + struct { + u_int8_t count; + u_int8_t isPathBroken:4; + u_int8_t reserved3:3; + u_int8_t widePortCapable:1; + + u_int8_t connectorIndex[2]; + u_int8_t reserved[4]; + u_int64_t sasAddr[2]; + u_int8_t reserved2[16]; + } pathInfo; + + u_int64_t rawSize; + u_int64_t nonCoercedSize; + u_int64_t coercedSize; + u_int16_t enclDeviceId; + u_int8_t enclIndex; + + union { + u_int8_t slotNumber; + u_int8_t enclConnectorIndex; + }; + + struct MR_PD_PROGRESS progInfo; + u_int8_t badBlockTableFull; + u_int8_t unusableInCurrentConfig; + u_int8_t vpdPage83Ext[64]; + u_int8_t powerState; + u_int8_t enclPosition; + u_int32_t allowedOps; + u_int16_t copyBackPartnerId; + u_int16_t enclPartnerDeviceId; + struct { + u_int16_t fdeCapable:1; + u_int16_t fdeEnabled:1; + u_int16_t secured:1; + u_int16_t locked:1; + u_int16_t foreign:1; + u_int16_t needsEKM:1; + u_int16_t reserved:10; + } security; + u_int8_t mediaType; + u_int8_t notCertified; + u_int8_t bridgeVendor[8]; + u_int8_t bridgeProductIdentification[16]; + u_int8_t bridgeProductRevisionLevel[4]; + u_int8_t satBridgeExists; + + u_int8_t interfaceType; + u_int8_t temperature; + u_int8_t emulatedBlockSize; + u_int16_t userDataBlockSize; + u_int16_t reserved2; + + struct { + u_int32_t piType:3; + u_int32_t piFormatted:1; + u_int32_t piEligible:1; + u_int32_t NCQ:1; + u_int32_t WCE:1; + u_int32_t commissionedSpare:1; + u_int32_t emergencySpare:1; + u_int32_t ineligibleForSSCD:1; + u_int32_t ineligibleForLd:1; + u_int32_t useSSEraseType:1; + u_int32_t wceUnchanged:1; + u_int32_t supportScsiUnmap:1; + u_int32_t reserved:18; + } properties; + + u_int64_t shieldDiagCompletionTime; + u_int8_t shieldCounter; + + u_int8_t linkSpeedOther; + u_int8_t reserved4[2]; + + struct { + u_int32_t bbmErrCountSupported:1; + u_int32_t bbmErrCount:31; + } bbmErr; + + u_int8_t reserved1[512-428]; +} __packed; + +struct mrsas_target { + u_int16_t target_id; + u_int32_t queue_depth; + u_int8_t interface_type; + u_int32_t max_io_size_kb; +} __packed; + /******************************************************************* * per-instance data ********************************************************************/ @@ -3066,10 +3271,14 @@ struct mrsas_softc { bus_addr_t raidmap_phys_addr[2]; bus_dma_tag_t mficmd_frame_tag; bus_dma_tag_t mficmd_sense_tag; + bus_addr_t evt_detail_phys_addr; bus_dma_tag_t evt_detail_tag; bus_dmamap_t evt_detail_dmamap; struct mrsas_evt_detail *evt_detail_mem; - bus_addr_t evt_detail_phys_addr; + bus_addr_t pd_info_phys_addr; + bus_dma_tag_t pd_info_tag; + bus_dmamap_t pd_info_dmamap; + struct mrsas_pd_info *pd_info_mem; struct mrsas_ctrl_info *ctrl_info; bus_dma_tag_t ctlr_info_tag; bus_dmamap_t ctlr_info_dmamap; @@ -3094,6 +3303,7 @@ struct mrsas_softc { bus_addr_t el_info_phys_addr; struct mrsas_pd_list pd_list[MRSAS_MAX_PD]; struct mrsas_pd_list local_pd_list[MRSAS_MAX_PD]; + struct mrsas_target target_list[MRSAS_MAX_TM_TARGETS]; u_int8_t ld_ids[MRSAS_MAX_LD_IDS]; struct taskqueue *ev_tq; struct task ev_task;