svn commit: r185034 - in stable/7/sys: . dev/mfi

Doug Ambrisko ambrisko at FreeBSD.org
Mon Nov 17 15:07:20 PST 2008


Author: ambrisko
Date: Mon Nov 17 23:07:18 2008
New Revision: 185034
URL: http://svn.freebsd.org/changeset/base/185034

Log:
  MFC 182085, 184897, 184933, 184974, 184975
  
  This addresses:
       1) New HW support from LSI (they want to get the HW support
          into a FreeBSD release before the HW comes out!).
       2) Bug fix in the ioctl path with zero length command.
       3) Adds functional support so that SCSI sense will work
          when requested from user-land.  This is a little strange,
          since they store a user-land pointer in the "data" space
          of the ioctl packet.  So copy the data out into another
          structure that is a union of the data and pointer (mfi_sense_ptr
          union).  This way we can cleanly use the pointer, as pointer on
          both 64bit and 32bit machines (i386/amd64).
  
  Submitted by:	LSI
  Approved by:	re (kib)

Modified:
  stable/7/sys/   (props changed)
  stable/7/sys/dev/mfi/mfi.c
  stable/7/sys/dev/mfi/mfi_ioctl.h
  stable/7/sys/dev/mfi/mfi_pci.c
  stable/7/sys/dev/mfi/mfireg.h
  stable/7/sys/dev/mfi/mfivar.h

Modified: stable/7/sys/dev/mfi/mfi.c
==============================================================================
--- stable/7/sys/dev/mfi/mfi.c	Mon Nov 17 22:46:29 2008	(r185033)
+++ stable/7/sys/dev/mfi/mfi.c	Mon Nov 17 23:07:18 2008	(r185034)
@@ -163,7 +163,11 @@ static void
 mfi_enable_intr_ppc(struct mfi_softc *sc)
 {
 	MFI_WRITE4(sc, MFI_ODCR0, 0xFFFFFFFF);
-	MFI_WRITE4(sc, MFI_OMSK, ~MFI_1078_EIM);
+	if (sc->mfi_flags & MFI_FLAGS_1078) {
+		MFI_WRITE4(sc, MFI_OMSK, ~MFI_1078_EIM);
+	} else if (sc->mfi_flags & MFI_FLAGS_GEN2) {
+		MFI_WRITE4(sc, MFI_OMSK, ~MFI_GEN2_EIM);
+	}
 }
 
 static int32_t
@@ -171,14 +175,14 @@ mfi_read_fw_status_xscale(struct mfi_sof
 {
 	return MFI_READ4(sc, MFI_OMSG0);
 }
- 
+
 static int32_t
 mfi_read_fw_status_ppc(struct mfi_softc *sc)
 {
 	return MFI_READ4(sc, MFI_OSP0);
 }
 
-static int 
+static int
 mfi_check_clear_intr_xscale(struct mfi_softc *sc)
 {
 	int32_t status;
@@ -189,28 +193,35 @@ mfi_check_clear_intr_xscale(struct mfi_s
 
 	MFI_WRITE4(sc, MFI_OSTS, status);
 	return 0;
- }
+}
 
-static int 
+static int
 mfi_check_clear_intr_ppc(struct mfi_softc *sc)
 {
 	int32_t status;
 
 	status = MFI_READ4(sc, MFI_OSTS);
-	if (!status)
-		return 1; 
+	if (sc->mfi_flags & MFI_FLAGS_1078) {
+		if (!(status & MFI_1078_RM)) {
+			return 1;
+		}
+	} else if (sc->mfi_flags & MFI_FLAGS_GEN2) {
+		if (!(status & MFI_GEN2_RM)) {
+			return 1;
+		}
+	}
 
 	MFI_WRITE4(sc, MFI_ODCR0, status);
 	return 0;
- }
+}
 
-static void 
+static void
 mfi_issue_cmd_xscale(struct mfi_softc *sc,uint32_t bus_add,uint32_t frame_cnt)
 {
 	MFI_WRITE4(sc, MFI_IQP,(bus_add >>3)|frame_cnt);
 }
-  
-static void 
+
+static void
 mfi_issue_cmd_ppc(struct mfi_softc *sc,uint32_t bus_add,uint32_t frame_cnt)
 {
 	MFI_WRITE4(sc, MFI_IQP, (bus_add |frame_cnt <<1)|1 );
@@ -1399,6 +1410,8 @@ mfi_bio_complete(struct mfi_command *cm)
 		device_printf(sc->mfi_dev, "I/O error, status= %d "
 		    "scsi_status= %d\n", hdr->cmd_status, hdr->scsi_status);
 		mfi_print_sense(cm->cm_sc, cm->cm_sense);
+	} else if (cm->cm_error != 0) {
+		bio->bio_flags |= BIO_ERROR;
 	}
 
 	mfi_release_command(cm);
@@ -1815,6 +1828,9 @@ mfi_check_command_post(struct mfi_softc 
 	case MFI_DCMD_CFG_ADD:
 		mfi_ldprobe(sc);
 		break;
+	case MFI_DCMD_CFG_FOREIGN_IMPORT:
+		mfi_ldprobe(sc);
+		break;
 	}
 }
 
@@ -1904,7 +1920,7 @@ mfi_ioctl(struct cdev *dev, u_long cmd, 
 	struct mfi_ioc_aen *aen;
 	struct mfi_command *cm = NULL;
 	uint32_t context;
-	uint8_t *sense_ptr;
+	union mfi_sense_ptr sense_ptr;
 	uint8_t *data = NULL, *temp;
 	int i;
 	struct mfi_ioc_passthru *iop = (struct mfi_ioc_passthru *)arg;
@@ -1986,8 +2002,9 @@ mfi_ioctl(struct cdev *dev, u_long cmd, 
 		context = cm->cm_frame->header.context;
 
 		bcopy(ioc->mfi_frame.raw, cm->cm_frame,
-		      2 * MFI_DCMD_FRAME_SIZE);  /* this isn't quite right */
-		cm->cm_total_frame_size = (sizeof(union mfi_sgl) * ioc->mfi_sge_count) + ioc->mfi_sgl_off;
+		    2 * MFI_DCMD_FRAME_SIZE);  /* this isn't quite right */
+		cm->cm_total_frame_size = (sizeof(union mfi_sgl)
+		    * ioc->mfi_sge_count) + ioc->mfi_sgl_off;
 		if (ioc->mfi_sge_count) {
 			cm->cm_sg =
 			    (union mfi_sgl *)&cm->cm_frame->bytes[ioc->mfi_sgl_off];
@@ -2001,7 +2018,8 @@ mfi_ioctl(struct cdev *dev, u_long cmd, 
 		if (cm->cm_flags == 0)
 			cm->cm_flags |= MFI_CMD_DATAIN | MFI_CMD_DATAOUT;
 		cm->cm_len = cm->cm_frame->header.data_len;
-		if (cm->cm_flags & (MFI_CMD_DATAIN | MFI_CMD_DATAOUT)) {
+		if (cm->cm_len &&
+		    (cm->cm_flags & (MFI_CMD_DATAIN | MFI_CMD_DATAOUT))) {
 			cm->cm_data = data = malloc(cm->cm_len, M_MFIBUF,
 			    M_WAITOK | M_ZERO);
 			if (cm->cm_data == NULL) {
@@ -2051,6 +2069,11 @@ mfi_ioctl(struct cdev *dev, u_long cmd, 
 		if (cm->cm_frame->header.cmd == MFI_CMD_DCMD)
 			locked = mfi_config_lock(sc, cm->cm_frame->dcmd.opcode);
 
+		if (cm->cm_frame->header.cmd == MFI_CMD_PD_SCSI_IO) {
+			cm->cm_frame->pass.sense_addr_lo = cm->cm_sense_busaddr;
+			cm->cm_frame->pass.sense_addr_hi = 0;
+		}
+
 		mtx_lock(&sc->mfi_io_lock);
 		error = mfi_check_command_pre(sc, cm);
 		if (error) {
@@ -2102,10 +2125,20 @@ mfi_ioctl(struct cdev *dev, u_long cmd, 
 		}
 
 		if (ioc->mfi_sense_len) {
-			/* copy out sense */
-			sense_ptr = &((struct mfi_ioc_packet*)arg)
-			    ->mfi_frame.raw[0];
-			error = copyout(cm->cm_sense, sense_ptr,
+			/* get user-space sense ptr then copy out sense */
+			bcopy(&((struct mfi_ioc_packet*)arg)
+			    ->mfi_frame.raw[ioc->mfi_sense_off],
+			    &sense_ptr.sense_ptr_data[0],
+			    sizeof(sense_ptr.sense_ptr_data));
+#ifdef __amd64__
+			if (cmd != MFI_CMD) {
+				/*
+				 * not 64bit native so zero out any address
+				 * over 32bit */
+				sense_ptr.addr.high = 0;
+			}
+#endif
+			error = copyout(cm->cm_sense, sense_ptr.user_space,
 			    ioc->mfi_sense_len);
 			if (error != 0) {
 				device_printf(sc->mfi_dev,
@@ -2207,7 +2240,7 @@ mfi_linux_ioctl_int(struct cdev *dev, u_
 	struct mfi_linux_ioc_aen l_aen;
 	struct mfi_command *cm = NULL;
 	struct mfi_aen *mfi_aen_entry;
-	uint8_t *sense_ptr;
+	union mfi_sense_ptr sense_ptr;
 	uint32_t context;
 	uint8_t *data = NULL, *temp;
 	int i;
@@ -2241,7 +2274,8 @@ mfi_linux_ioctl_int(struct cdev *dev, u_
 
 		bcopy(l_ioc.lioc_frame.raw, cm->cm_frame,
 		      2 * MFI_DCMD_FRAME_SIZE);	/* this isn't quite right */
-		cm->cm_total_frame_size = (sizeof(union mfi_sgl) * l_ioc.lioc_sge_count) + l_ioc.lioc_sgl_off;
+		cm->cm_total_frame_size = (sizeof(union mfi_sgl)
+		      * l_ioc.lioc_sge_count) + l_ioc.lioc_sgl_off;
 		if (l_ioc.lioc_sge_count)
 			cm->cm_sg =
 			    (union mfi_sgl *)&cm->cm_frame->bytes[l_ioc.lioc_sgl_off];
@@ -2251,7 +2285,8 @@ mfi_linux_ioctl_int(struct cdev *dev, u_
 		if (cm->cm_frame->header.flags & MFI_FRAME_DATAOUT)
 			cm->cm_flags |= MFI_CMD_DATAOUT;
 		cm->cm_len = cm->cm_frame->header.data_len;
-		if (cm->cm_flags & (MFI_CMD_DATAIN | MFI_CMD_DATAOUT)) {
+		if (cm->cm_len &&
+		      (cm->cm_flags & (MFI_CMD_DATAIN | MFI_CMD_DATAOUT))) {
 			cm->cm_data = data = malloc(cm->cm_len, M_MFIBUF,
 			    M_WAITOK | M_ZERO);
 			if (cm->cm_data == NULL) {
@@ -2283,6 +2318,11 @@ mfi_linux_ioctl_int(struct cdev *dev, u_
 		if (cm->cm_frame->header.cmd == MFI_CMD_DCMD)
 			locked = mfi_config_lock(sc, cm->cm_frame->dcmd.opcode);
 
+		if (cm->cm_frame->header.cmd == MFI_CMD_PD_SCSI_IO) {
+			cm->cm_frame->pass.sense_addr_lo = cm->cm_sense_busaddr;
+			cm->cm_frame->pass.sense_addr_hi = 0;
+		}
+
 		mtx_lock(&sc->mfi_io_lock);
 		error = mfi_check_command_pre(sc, cm);
 		if (error) {
@@ -2316,10 +2356,19 @@ mfi_linux_ioctl_int(struct cdev *dev, u_
 		}
 
 		if (l_ioc.lioc_sense_len) {
-			/* copy out sense */
-			sense_ptr = &((struct mfi_linux_ioc_packet*)arg)
-			    ->lioc_frame.raw[0];
-			error = copyout(cm->cm_sense, sense_ptr,
+			/* get user-space sense ptr then copy out sense */
+			bcopy(&((struct mfi_linux_ioc_packet*)arg)
+                            ->lioc_frame.raw[l_ioc.lioc_sense_off],
+			    &sense_ptr.sense_ptr_data[0],
+			    sizeof(sense_ptr.sense_ptr_data));
+#ifdef __amd64__
+			/*
+			 * only 32bit Linux support so zero out any
+			 * address over 32bit
+			 */
+			sense_ptr.addr.high = 0;
+#endif
+			error = copyout(cm->cm_sense, sense_ptr.user_space,
 			    l_ioc.lioc_sense_len);
 			if (error != 0) {
 				device_printf(sc->mfi_dev,

Modified: stable/7/sys/dev/mfi/mfi_ioctl.h
==============================================================================
--- stable/7/sys/dev/mfi/mfi_ioctl.h	Mon Nov 17 22:46:29 2008	(r185033)
+++ stable/7/sys/dev/mfi/mfi_ioctl.h	Mon Nov 17 23:07:18 2008	(r185034)
@@ -50,6 +50,16 @@ union mfi_statrequest {
 	struct mfi_qstat	ms_qstat;
 };
 
+#define MAX_SPACE_FOR_SENSE_PTR		32
+union mfi_sense_ptr {
+	uint8_t		sense_ptr_data[MAX_SPACE_FOR_SENSE_PTR];
+	void 		*user_space;
+	struct {
+		uint32_t	low;
+		uint32_t	high;
+	} addr;
+} __packed;
+
 #define MAX_IOCTL_SGE	16
 
 struct mfi_ioc_packet {

Modified: stable/7/sys/dev/mfi/mfi_pci.c
==============================================================================
--- stable/7/sys/dev/mfi/mfi_pci.c	Mon Nov 17 22:46:29 2008	(r185033)
+++ stable/7/sys/dev/mfi/mfi_pci.c	Mon Nov 17 23:07:18 2008	(r185034)
@@ -118,7 +118,14 @@ struct mfi_ident {
 	{0x1000, 0x0413, 0xffff, 0xffff, MFI_FLAGS_1064R, "LSI MegaSAS 1064R"}, /* Verde ZCR */
 	{0x1028, 0x0015, 0xffff, 0xffff, MFI_FLAGS_1064R, "Dell PERC 5/i"},
 	{0x1000, 0x0060, 0x1028, 0xffff, MFI_FLAGS_1078,  "Dell PERC 6"},
-	{0x1000, 0x0060, 0xffff, 0xffff, MFI_FLAGS_1078,  "LSI MegaSAS 1078"},
+ 	{0x1000, 0x0060, 0xffff, 0xffff, MFI_FLAGS_1078,  "LSI MegaSAS 1078"},
+	{0x1000, 0x0079, 0x1028, 0x1f15, MFI_FLAGS_GEN2,  "Dell PERC 607E Adapter"},
+	{0x1000, 0x0079, 0x1028, 0x1f16, MFI_FLAGS_GEN2,  "Dell PERC 607I Adapter"},
+	{0x1000, 0x0079, 0x1028, 0x1f17, MFI_FLAGS_GEN2,  "Dell PERC 607I Integrated"},
+	{0x1000, 0x0079, 0x1028, 0x1f18, MFI_FLAGS_GEN2,  "Dell PERC 607I Modular"},
+	{0x1000, 0x0078, 0xffff, 0xffff, MFI_FLAGS_GEN2,  "LSI MegaSAS Gen2"},
+	{0x1000, 0x0079, 0xffff, 0xffff, MFI_FLAGS_GEN2,  "LSI MegaSAS Gen2"},
+	{0x1000, 0x007c, 0xffff, 0xffff, MFI_FLAGS_1078,  "LSI MegaSAS 1078"},
 	{0, 0, 0, 0, 0, NULL}
 };
 
@@ -163,6 +170,8 @@ mfi_pci_attach(device_t dev)
 	sc = device_get_softc(dev);
 	bzero(sc, sizeof(*sc));
 	sc->mfi_dev = dev;
+	m = mfi_find_ident(dev);
+	sc->mfi_flags = m->flags;
 
 	/* Verify that the adapter can be set up in PCI space */
 	command = pci_read_config(dev, PCIR_COMMAND, 2);
@@ -179,7 +188,14 @@ mfi_pci_attach(device_t dev)
 	}
 
 	/* Allocate PCI registers */
-	sc->mfi_regs_rid = PCIR_BAR(0);
+	if ((sc->mfi_flags & MFI_FLAGS_1064R) ||
+	    (sc->mfi_flags & MFI_FLAGS_1078)) {
+		/* 1068/1078: Memory mapped BAR is at offset 0x10 */
+		sc->mfi_regs_rid = PCIR_BAR(0);
+	} else if (sc->mfi_flags & MFI_FLAGS_GEN2) {
+		/* GEN2: Memory mapped BAR is at offset 0x14 */
+		sc->mfi_regs_rid = PCIR_BAR(1);
+	}
 	if ((sc->mfi_regs_resource = bus_alloc_resource_any(sc->mfi_dev,
 	    SYS_RES_MEMORY, &sc->mfi_regs_rid, RF_ACTIVE)) == NULL) {
 		device_printf(dev, "Cannot allocate PCI registers\n");
@@ -206,9 +222,6 @@ mfi_pci_attach(device_t dev)
 		goto out;
 	}
 
-	m = mfi_find_ident(dev);
-	sc->mfi_flags = m->flags;
-
 	error = mfi_attach(sc);
 out:
 	if (error) {

Modified: stable/7/sys/dev/mfi/mfireg.h
==============================================================================
--- stable/7/sys/dev/mfi/mfireg.h	Mon Nov 17 22:46:29 2008	(r185033)
+++ stable/7/sys/dev/mfi/mfireg.h	Mon Nov 17 23:07:18 2008	(r185034)
@@ -89,10 +89,16 @@ __FBSDID("$FreeBSD$");
 #define MFI_ODCR0	0xa0 		/* outbound doorbell clear register0  */
 #define MFI_OSP0	0xb0 		/* outbound scratch pad0  */
 #define MFI_1078_EIM	0x80000004 	/* 1078 enable intrrupt mask  */
-#define MFI_RMI		0x2 		/* reply message interrupt  */       
+#define MFI_RMI		0x2 		/* reply message interrupt  */
 #define MFI_1078_RM	0x80000000 	/* reply 1078 message interrupt  */
 #define MFI_ODC		0x4 		/* outbound doorbell change interrupt */
 
+/*
+ * GEN2 specific changes
+ */
+#define MFI_GEN2_EIM	0x00000005	/* GEN2 enable interrupt mask */
+#define MFI_GEN2_RM	0x00000001	/* reply GEN2 message interrupt */
+
 /* Bits for MFI_OSTS */
 #define MFI_OSTS_INTR_VALID	0x00000002
 
@@ -153,6 +159,7 @@ typedef enum {
 	MFI_DCMD_CFG_READ =		0x04010000,
 	MFI_DCMD_CFG_ADD =		0x04020000,
 	MFI_DCMD_CFG_CLEAR =		0x04030000,
+	MFI_DCMD_CFG_FOREIGN_IMPORT =	0x04060400,
 	MFI_DCMD_CLUSTER =		0x08000000,
 	MFI_DCMD_CLUSTER_RESET_ALL =	0x08010100,
 	MFI_DCMD_CLUSTER_RESET_LD =	0x08010200

Modified: stable/7/sys/dev/mfi/mfivar.h
==============================================================================
--- stable/7/sys/dev/mfi/mfivar.h	Mon Nov 17 22:46:29 2008	(r185033)
+++ stable/7/sys/dev/mfi/mfivar.h	Mon Nov 17 23:07:18 2008	(r185034)
@@ -133,6 +133,7 @@ struct mfi_softc {
 #define MFI_FLAGS_STOP		(1<<3)
 #define MFI_FLAGS_1064R		(1<<4)
 #define MFI_FLAGS_1078		(1<<5)
+#define MFI_FLAGS_GEN2		(1<<6)
 
 	struct mfi_hwcomms		*mfi_comms;
 	TAILQ_HEAD(,mfi_command)	mfi_free;


More information about the svn-src-stable mailing list