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;
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "[EMAIL PROTECTED]"

Reply via email to