svn commit: r342065 - head/sys/dev/mrsas

Kashyap D Desai kadesai at FreeBSD.org
Fri Dec 14 08:03:29 UTC 2018


Author: kadesai
Date: Fri Dec 14 08:03:28 2018
New Revision: 342065
URL: https://svnweb.freebsd.org/changeset/base/342065

Log:
  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 at broadcom.com>
  Reviewed by:  Kashyap Desai <Kashyap.Desai at broadcom.com>
  Approved by:  ken
  MFC after:  3 days
  Sponsored by:   Broadcom Inc

Modified:
  head/sys/dev/mrsas/mrsas.c
  head/sys/dev/mrsas/mrsas.h

Modified: head/sys/dev/mrsas/mrsas.c
==============================================================================
--- head/sys/dev/mrsas/mrsas.c	Fri Dec 14 08:02:44 2018	(r342064)
+++ head/sys/dev/mrsas/mrsas.c	Fri Dec 14 08:03:28 2018	(r342065)
@@ -90,6 +90,8 @@ static void mrsas_update_ext_vd_details(struct mrsas_s
 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 @@ attach_fail:
 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 !!! "
@@ -1216,6 +1226,16 @@ mrsas_free_mem(struct mrsas_softc *sc)
 		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
 	 */
 	if (sc->mfi_cmd_list) {
@@ -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,7 +2029,39 @@ 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,7 +4330,114 @@ 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 @@ dcmd_timeout:
 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:

Modified: head/sys/dev/mrsas/mrsas.h
==============================================================================
--- head/sys/dev/mrsas/mrsas.h	Fri Dec 14 08:02:44 2018	(r342064)
+++ head/sys/dev/mrsas/mrsas.h	Fri Dec 14 08:03:28 2018	(r342065)
@@ -740,6 +740,7 @@ Mpi2IOCInitRequest_t, MPI2_POINTER pMpi2IOCInitRequest
 #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;


More information about the svn-src-all mailing list