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 <sumit.saxena@broadcom.com>
Reviewed by:  Kashyap Desai <Kashyap.Desai@broadcom.com>
Approved by:  ken
MFC after:  3 days
Sponsored by:   Broadcom Inc
This commit is contained in:
kadesai 2018-12-14 08:03:28 +00:00
parent 514f953e0e
commit dc69dfc3bf
2 changed files with 400 additions and 4 deletions

View File

@ -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:

View File

@ -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;