svn commit: r189986 - in stable/6/sys: . dev/mfi

Doug Ambrisko ambrisko at FreeBSD.org
Wed Mar 18 13:42:01 PDT 2009


Author: ambrisko
Date: Wed Mar 18 20:42:00 2009
New Revision: 189986
URL: http://svn.freebsd.org/changeset/base/189986

Log:
  MF7: r185034 which brings in new HW support, fix some bugs in the API
       for the management ioctl.
  
  Submitted by:	LSI

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

Modified: stable/6/sys/dev/mfi/mfi.c
==============================================================================
--- stable/6/sys/dev/mfi/mfi.c	Wed Mar 18 20:22:21 2009	(r189985)
+++ stable/6/sys/dev/mfi/mfi.c	Wed Mar 18 20:42:00 2009	(r189986)
@@ -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,
@@ -2203,7 +2236,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;
@@ -2237,7 +2270,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];
@@ -2247,7 +2281,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) {
@@ -2279,6 +2314,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) {
@@ -2312,10 +2352,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/6/sys/dev/mfi/mfi_ioctl.h
==============================================================================
--- stable/6/sys/dev/mfi/mfi_ioctl.h	Wed Mar 18 20:22:21 2009	(r189985)
+++ stable/6/sys/dev/mfi/mfi_ioctl.h	Wed Mar 18 20:42:00 2009	(r189986)
@@ -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/6/sys/dev/mfi/mfi_pci.c
==============================================================================
--- stable/6/sys/dev/mfi/mfi_pci.c	Wed Mar 18 20:22:21 2009	(r189985)
+++ stable/6/sys/dev/mfi/mfi_pci.c	Wed Mar 18 20:42:00 2009	(r189986)
@@ -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/6/sys/dev/mfi/mfireg.h
==============================================================================
--- stable/6/sys/dev/mfi/mfireg.h	Wed Mar 18 20:22:21 2009	(r189985)
+++ stable/6/sys/dev/mfi/mfireg.h	Wed Mar 18 20:42:00 2009	(r189986)
@@ -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/6/sys/dev/mfi/mfivar.h
==============================================================================
--- stable/6/sys/dev/mfi/mfivar.h	Wed Mar 18 20:22:21 2009	(r189985)
+++ stable/6/sys/dev/mfi/mfivar.h	Wed Mar 18 20:42:00 2009	(r189986)
@@ -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-6 mailing list