Author: mav
Date: Thu Sep 29 08:37:53 2011
New Revision: 225869
URL: http://svn.freebsd.org/changeset/base/225869

Log:
   - Add special support for the MFI_CMD ioctl with MFI_CMD_STP command, used
  by present MegaCLI version. It has some special meaning for the first s/g
  list entry, while the main s/g list begins from the the second entry, and
  those lists should remain separate after loading to the busdma map.
   - Fix bug in 32bit ioctl compatibility shims when s/g list consists of
  more then on element.
  
  Sponsored by: iXsystems, inc.
  MFC after:    3 days

Modified:
  head/sys/dev/mfi/mfi.c
  head/sys/dev/mfi/mfivar.h

Modified: head/sys/dev/mfi/mfi.c
==============================================================================
--- head/sys/dev/mfi/mfi.c      Thu Sep 29 06:31:42 2011        (r225868)
+++ head/sys/dev/mfi/mfi.c      Thu Sep 29 08:37:53 2011        (r225869)
@@ -1488,7 +1488,7 @@ mfi_data_cb(void *arg, bus_dma_segment_t
        struct mfi_command *cm;
        union mfi_sgl *sgl;
        struct mfi_softc *sc;
-       int i, dir;
+       int i, j, first, dir;
 
        cm = (struct mfi_command *)arg;
        sc = cm->cm_sc;
@@ -1502,19 +1502,33 @@ mfi_data_cb(void *arg, bus_dma_segment_t
                return;
        }
 
+       j = 0;
+       if (cm->cm_frame->header.cmd == MFI_CMD_STP) {
+               first = cm->cm_stp_len;
+               if ((sc->mfi_flags & MFI_FLAGS_SG64) == 0) {
+                       sgl->sg32[j].addr = segs[0].ds_addr;
+                       sgl->sg32[j++].len = first;
+               } else {
+                       sgl->sg64[j].addr = segs[0].ds_addr;
+                       sgl->sg64[j++].len = first;
+               }
+       } else
+               first = 0;
        if ((sc->mfi_flags & MFI_FLAGS_SG64) == 0) {
                for (i = 0; i < nsegs; i++) {
-                       sgl->sg32[i].addr = segs[i].ds_addr;
-                       sgl->sg32[i].len = segs[i].ds_len;
+                       sgl->sg32[j].addr = segs[i].ds_addr + first;
+                       sgl->sg32[j++].len = segs[i].ds_len - first;
+                       first = 0;
                }
        } else {
                for (i = 0; i < nsegs; i++) {
-                       sgl->sg64[i].addr = segs[i].ds_addr;
-                       sgl->sg64[i].len = segs[i].ds_len;
+                       sgl->sg64[j].addr = segs[i].ds_addr + first;
+                       sgl->sg64[j++].len = segs[i].ds_len - first;
+                       first = 0;
                }
                hdr->flags |= MFI_FRAME_SGL64;
        }
-       hdr->sg_count = nsegs;
+       hdr->sg_count = j;
 
        dir = 0;
        if (cm->cm_flags & MFI_CMD_DATAIN) {
@@ -1525,6 +1539,8 @@ mfi_data_cb(void *arg, bus_dma_segment_t
                dir |= BUS_DMASYNC_PREWRITE;
                hdr->flags |= MFI_FRAME_DIR_WRITE;
        }
+       if (cm->cm_frame->header.cmd == MFI_CMD_STP)
+               dir |= BUS_DMASYNC_PREWRITE;
        bus_dmamap_sync(sc->mfi_buffer_dmat, cm->cm_dmamap, dir);
        cm->cm_flags |= MFI_CMD_MAPPED;
 
@@ -1602,7 +1618,8 @@ mfi_complete(struct mfi_softc *sc, struc
 
        if ((cm->cm_flags & MFI_CMD_MAPPED) != 0) {
                dir = 0;
-               if (cm->cm_flags & MFI_CMD_DATAIN)
+               if ((cm->cm_flags & MFI_CMD_DATAIN) ||
+                   (cm->cm_frame->header.cmd == MFI_CMD_STP))
                        dir |= BUS_DMASYNC_POSTREAD;
                if (cm->cm_flags & MFI_CMD_DATAOUT)
                        dir |= BUS_DMASYNC_POSTWRITE;
@@ -1927,7 +1944,8 @@ mfi_ioctl(struct cdev *dev, u_long cmd, 
        struct mfi_command *cm = NULL;
        uint32_t context;
        union mfi_sense_ptr sense_ptr;
-       uint8_t *data = NULL, *temp;
+       uint8_t *data = NULL, *temp, *addr;
+       size_t len;
        int i;
        struct mfi_ioc_passthru *iop = (struct mfi_ioc_passthru *)arg;
 #ifdef __amd64__
@@ -2024,6 +2042,21 @@ 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_frame->header.cmd == MFI_CMD_STP) {
+#ifdef __amd64__
+                       if (cmd == MFI_CMD) {
+#endif
+                               /* Native */
+                               cm->cm_stp_len = ioc->mfi_sgl[0].iov_len;
+#ifdef __amd64__
+                       } else {
+                               /* 32bit on 64bit */
+                               ioc32 = (struct mfi_ioc_packet32 *)ioc;
+                               cm->cm_stp_len = ioc32->mfi_sgl[0].iov_len;
+                       }
+#endif
+                       cm->cm_len += cm->cm_stp_len;
+               }
                if (cm->cm_len &&
                    (cm->cm_flags & (MFI_CMD_DATAIN | MFI_CMD_DATAOUT))) {
                        cm->cm_data = data = malloc(cm->cm_len, M_MFIBUF,
@@ -2040,35 +2073,30 @@ mfi_ioctl(struct cdev *dev, u_long cmd, 
                cm->cm_frame->header.context = context;
 
                temp = data;
-               if (cm->cm_flags & MFI_CMD_DATAOUT) {
+               if ((cm->cm_flags & MFI_CMD_DATAOUT) ||
+                   (cm->cm_frame->header.cmd == MFI_CMD_STP)) {
                        for (i = 0; i < ioc->mfi_sge_count; i++) {
 #ifdef __amd64__
                                if (cmd == MFI_CMD) {
+#endif
                                        /* Native */
-                                       error = copyin(ioc->mfi_sgl[i].iov_base,
-                                              temp,
-                                              ioc->mfi_sgl[i].iov_len);
+                                       addr = ioc->mfi_sgl[i].iov_base;
+                                       len = ioc->mfi_sgl[i].iov_len;
+#ifdef __amd64__
                                } else {
-                                       void *temp_convert;
-                                       /* 32bit */
+                                       /* 32bit on 64bit */
                                        ioc32 = (struct mfi_ioc_packet32 *)ioc;
-                                       temp_convert =
-                                           PTRIN(ioc32->mfi_sgl[i].iov_base);
-                                       error = copyin(temp_convert,
-                                              temp,
-                                              ioc32->mfi_sgl[i].iov_len);
+                                       addr = 
PTRIN(ioc32->mfi_sgl[i].iov_base);
+                                       len = ioc32->mfi_sgl[i].iov_len;
                                }
-#else
-                               error = copyin(ioc->mfi_sgl[i].iov_base,
-                                      temp,
-                                      ioc->mfi_sgl[i].iov_len);
 #endif
+                               error = copyin(addr, temp, len);
                                if (error != 0) {
                                        device_printf(sc->mfi_dev,
                                            "Copy in failed\n");
                                        goto out;
                                }
-                               temp = &temp[ioc->mfi_sgl[i].iov_len];
+                               temp = &temp[len];
                        }
                }
 
@@ -2098,35 +2126,30 @@ mfi_ioctl(struct cdev *dev, u_long cmd, 
                mtx_unlock(&sc->mfi_io_lock);
 
                temp = data;
-               if (cm->cm_flags & MFI_CMD_DATAIN) {
+               if ((cm->cm_flags & MFI_CMD_DATAIN) ||
+                   (cm->cm_frame->header.cmd == MFI_CMD_STP)) {
                        for (i = 0; i < ioc->mfi_sge_count; i++) {
 #ifdef __amd64__
                                if (cmd == MFI_CMD) {
+#endif
                                        /* Native */
-                                       error = copyout(temp,
-                                               ioc->mfi_sgl[i].iov_base,
-                                               ioc->mfi_sgl[i].iov_len);
+                                       addr = ioc->mfi_sgl[i].iov_base;
+                                       len = ioc->mfi_sgl[i].iov_len;
+#ifdef __amd64__
                                } else {
-                                       void *temp_convert;
-                                       /* 32bit */
+                                       /* 32bit on 64bit */
                                        ioc32 = (struct mfi_ioc_packet32 *)ioc;
-                                       temp_convert =
-                                           PTRIN(ioc32->mfi_sgl[i].iov_base);
-                                       error = copyout(temp,
-                                               temp_convert,
-                                               ioc32->mfi_sgl[i].iov_len);
+                                       addr = 
PTRIN(ioc32->mfi_sgl[i].iov_base);
+                                       len = ioc32->mfi_sgl[i].iov_len;
                                }
-#else
-                               error = copyout(temp,
-                                       ioc->mfi_sgl[i].iov_base,
-                                       ioc->mfi_sgl[i].iov_len);
 #endif
+                               error = copyout(temp, addr, len);
                                if (error != 0) {
                                        device_printf(sc->mfi_dev,
                                            "Copy out failed\n");
                                        goto out;
                                }
-                               temp = &temp[ioc->mfi_sgl[i].iov_len];
+                               temp = &temp[len];
                        }
                }
 

Modified: head/sys/dev/mfi/mfivar.h
==============================================================================
--- head/sys/dev/mfi/mfivar.h   Thu Sep 29 06:31:42 2011        (r225868)
+++ head/sys/dev/mfi/mfivar.h   Thu Sep 29 08:37:53 2011        (r225869)
@@ -87,6 +87,7 @@ struct mfi_command {
        union mfi_sgl           *cm_sg;
        void                    *cm_data;
        int                     cm_len;
+       int                     cm_stp_len;
        int                     cm_total_frame_size;
        int                     cm_extra_frames;
        int                     cm_flags;
_______________________________________________
svn-src-head@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to