Author: ambrisko
Date: Wed Nov 12 22:44:50 2008
New Revision: 184897
URL: http://svn.freebsd.org/changeset/base/184897

Log:
  - Fix from jhb for failing I/O request when bus_dmamap_load fails.
  - Fix to ioctl path in which the length could be 0 which means
    no data in/out from LSI.
  - Fix to ioctl path in which the data in the sense data space
    of the ioctl packet is a really a pointer to some location in
    user-space.  From LSI re-worked a bit by me.
  - Add HW support for next gen cards from LSI.
  
  Thanks to LSI for their support!
  
  Submitted by: jhb, LSI
  MFC after:    3 days

Modified:
  head/sys/dev/mfi/mfi.c
  head/sys/dev/mfi/mfi_ioctl.h
  head/sys/dev/mfi/mfi_pci.c
  head/sys/dev/mfi/mfireg.h
  head/sys/dev/mfi/mfivar.h

Modified: head/sys/dev/mfi/mfi.c
==============================================================================
--- head/sys/dev/mfi/mfi.c      Wed Nov 12 22:14:05 2008        (r184896)
+++ head/sys/dev/mfi/mfi.c      Wed Nov 12 22:44:50 2008        (r184897)
@@ -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;
@@ -191,26 +195,33 @@ mfi_check_clear_intr_xscale(struct mfi_s
        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) {
@@ -2102,10 +2120,12 @@ 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));
+                       error = copyout(cm->cm_sense, sense_ptr.user_space,
                            ioc->mfi_sense_len);
                        if (error != 0) {
                                device_printf(sc->mfi_dev,
@@ -2207,7 +2227,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 +2261,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 +2272,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) {
@@ -2316,10 +2338,12 @@ 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));
+                       error = copyout(cm->cm_sense, sense_ptr.user_space,
                            l_ioc.lioc_sense_len);
                        if (error != 0) {
                                device_printf(sc->mfi_dev,

Modified: head/sys/dev/mfi/mfi_ioctl.h
==============================================================================
--- head/sys/dev/mfi/mfi_ioctl.h        Wed Nov 12 22:14:05 2008        
(r184896)
+++ head/sys/dev/mfi/mfi_ioctl.h        Wed Nov 12 22:44:50 2008        
(r184897)
@@ -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: head/sys/dev/mfi/mfi_pci.c
==============================================================================
--- head/sys/dev/mfi/mfi_pci.c  Wed Nov 12 22:14:05 2008        (r184896)
+++ head/sys/dev/mfi/mfi_pci.c  Wed Nov 12 22:44:50 2008        (r184897)
@@ -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: head/sys/dev/mfi/mfireg.h
==============================================================================
--- head/sys/dev/mfi/mfireg.h   Wed Nov 12 22:14:05 2008        (r184896)
+++ head/sys/dev/mfi/mfireg.h   Wed Nov 12 22:44:50 2008        (r184897)
@@ -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: head/sys/dev/mfi/mfivar.h
==============================================================================
--- head/sys/dev/mfi/mfivar.h   Wed Nov 12 22:14:05 2008        (r184896)
+++ head/sys/dev/mfi/mfivar.h   Wed Nov 12 22:44:50 2008        (r184897)
@@ -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