Author: marius
Date: Sat Feb 11 12:03:44 2012
New Revision: 231518
URL: http://svn.freebsd.org/changeset/base/231518

Log:
  Flesh out support for SAS1078 and SAS1078DE (which are said to actually
  be the same chip):
  - The I/O port resource may not be available with these. However, given
    that we actually only need this resource for some controllers that
    require their firmware to be up- and downloaded (which excludes the
    SAS1078{,DE}) just handle failure to allocate this resource gracefully
    when possible. While at it, generally put non-fatal resource allocation
    failures under bootverbose.
  - SAS1078{,DE} use a different hard reset protocol.
  - Add workarounds for the 36GB physical address limitation of scatter/
    gather elements of these controllers.
  
  Tested by:    Slawa Olhovchenkov
  
  PR:   149220 (remaining part)

Modified:
  head/sys/dev/mpt/mpt.c
  head/sys/dev/mpt/mpt.h
  head/sys/dev/mpt/mpt_cam.c
  head/sys/dev/mpt/mpt_pci.c
  head/sys/dev/mpt/mpt_reg.h

Modified: head/sys/dev/mpt/mpt.c
==============================================================================
--- head/sys/dev/mpt/mpt.c      Sat Feb 11 11:34:53 2012        (r231517)
+++ head/sys/dev/mpt/mpt.c      Sat Feb 11 12:03:44 2012        (r231518)
@@ -1053,6 +1053,12 @@ mpt_hard_reset(struct mpt_softc *mpt)
 
        mpt_lprt(mpt, MPT_PRT_DEBUG, "hard reset\n");
 
+       if (mpt->is_1078) {
+               mpt_write(mpt, MPT_OFFSET_RESET_1078, 0x07);
+               DELAY(1000);
+               return;
+       }
+
        error = mpt_enable_diag_mode(mpt);
        if (error) {
                mpt_prt(mpt, "WARNING - Could not enter diagnostic mode !\n");
@@ -2450,6 +2456,11 @@ mpt_download_fw(struct mpt_softc *mpt)
        uint32_t ext_offset;
        uint32_t data;
 
+       if (mpt->pci_pio_reg == NULL) {
+               mpt_prt(mpt, "No PIO resource!\n");
+               return (ENXIO);
+       }
+
        mpt_prt(mpt, "Downloading Firmware - Image Size %d\n",
                mpt->fw_image_size);
 

Modified: head/sys/dev/mpt/mpt.h
==============================================================================
--- head/sys/dev/mpt/mpt.h      Sat Feb 11 11:34:53 2012        (r231517)
+++ head/sys/dev/mpt/mpt.h      Sat Feb 11 12:03:44 2012        (r231518)
@@ -608,7 +608,7 @@ struct mpt_softc {
 #endif
        uint32_t                mpt_pers_mask;
        uint32_t
-                               : 8,
+                               : 7,
                unit            : 8,
                ready           : 1,
                fw_uploaded     : 1,
@@ -625,7 +625,8 @@ struct mpt_softc {
                disabled        : 1,
                is_spi          : 1,
                is_sas          : 1,
-               is_fc           : 1;
+               is_fc           : 1,
+               is_1078         : 1;
 
        u_int                   cfg_role;
        u_int                   role;   /* role: none, ini, target, both */
@@ -982,12 +983,14 @@ mpt_read(struct mpt_softc *mpt, int offs
 static __inline void
 mpt_pio_write(struct mpt_softc *mpt, size_t offset, uint32_t val)
 {
+       KASSERT(mpt->pci_pio_reg != NULL, ("no PIO resource"));
        bus_space_write_4(mpt->pci_pio_st, mpt->pci_pio_sh, offset, val);
 }
 
 static __inline uint32_t
 mpt_pio_read(struct mpt_softc *mpt, int offset)
 {
+       KASSERT(mpt->pci_pio_reg != NULL, ("no PIO resource"));
        return (bus_space_read_4(mpt->pci_pio_st, mpt->pci_pio_sh, offset));
 }
 /*********************** Reply Frame/Request Management 
***********************/

Modified: head/sys/dev/mpt/mpt_cam.c
==============================================================================
--- head/sys/dev/mpt/mpt_cam.c  Sat Feb 11 11:34:53 2012        (r231517)
+++ head/sys/dev/mpt/mpt_cam.c  Sat Feb 11 12:03:44 2012        (r231518)
@@ -1279,8 +1279,9 @@ mpt_execute_req_a64(void *arg, bus_dma_s
        char *mpt_off;
        union ccb *ccb;
        struct mpt_softc *mpt;
-       int seg, first_lim;
-       uint32_t flags, nxt_off;
+       bus_addr_t chain_list_addr;
+       int first_lim, seg, this_seg_lim;
+       uint32_t addr, cur_off, flags, nxt_off, tf;
        void *sglp = NULL;
        MSG_REQUEST_HEADER *hdrp;
        SGE_SIMPLE64 *se;
@@ -1434,16 +1435,20 @@ bad:
 
        se = (SGE_SIMPLE64 *) sglp;
        for (seg = 0; seg < first_lim; seg++, se++, dm_segs++) {
-               uint32_t tf;
-
+               tf = flags;
                memset(se, 0, sizeof (*se));
+               MPI_pSGE_SET_LENGTH(se, dm_segs->ds_len);
                se->Address.Low = htole32(dm_segs->ds_addr & 0xffffffff);
                if (sizeof(bus_addr_t) > 4) {
-                       se->Address.High =
-                           htole32(((uint64_t)dm_segs->ds_addr) >> 32);
+                       addr = ((uint64_t)dm_segs->ds_addr) >> 32;
+                       /* SAS1078 36GB limitation WAR */
+                       if (mpt->is_1078 && (((uint64_t)dm_segs->ds_addr +
+                           MPI_SGE_LENGTH(se->FlagsLength)) >> 32) == 9) {
+                               addr |= (1 << 31);
+                               tf |= MPI_SGE_FLAGS_LOCAL_ADDRESS;
+                       }
+                       se->Address.High = htole32(addr);
                }
-               MPI_pSGE_SET_LENGTH(se, dm_segs->ds_len);
-               tf = flags;
                if (seg == first_lim - 1) {
                        tf |= MPI_SGE_FLAGS_LAST_ELEMENT;
                }
@@ -1468,15 +1473,11 @@ bad:
 
        /*
         * Make up the rest of the data segments out of a chain element
-        * (contiained in the current request frame) which points to
+        * (contained in the current request frame) which points to
         * SIMPLE64 elements in the next request frame, possibly ending
         * with *another* chain element (if there's more).
         */
        while (seg < nseg) {
-               int this_seg_lim;
-               uint32_t tf, cur_off;
-               bus_addr_t chain_list_addr;
-
                /*
                 * Point to the chain descriptor. Note that the chain
                 * descriptor is at the end of the *previous* list (whether
@@ -1504,7 +1505,7 @@ bad:
                nxt_off += MPT_RQSL(mpt);
 
                /*
-                * Now initialized the chain descriptor.
+                * Now initialize the chain descriptor.
                 */
                memset(ce, 0, sizeof (*ce));
 
@@ -1554,16 +1555,24 @@ bad:
                 * set the end of list and end of buffer flags.
                 */
                while (seg < this_seg_lim) {
+                       tf = flags;
                        memset(se, 0, sizeof (*se));
+                       MPI_pSGE_SET_LENGTH(se, dm_segs->ds_len);
                        se->Address.Low = htole32(dm_segs->ds_addr &
                            0xffffffff);
                        if (sizeof (bus_addr_t) > 4) {
-                               se->Address.High =
-                                   htole32(((uint64_t)dm_segs->ds_addr) >> 32);
+                               addr = ((uint64_t)dm_segs->ds_addr) >> 32;
+                               /* SAS1078 36GB limitation WAR */
+                               if (mpt->is_1078 &&
+                                   (((uint64_t)dm_segs->ds_addr +
+                                   MPI_SGE_LENGTH(se->FlagsLength)) >>
+                                   32) == 9) {
+                                       addr |= (1 << 31);
+                                       tf |= MPI_SGE_FLAGS_LOCAL_ADDRESS;
+                               }
+                               se->Address.High = htole32(addr);
                        }
-                       MPI_pSGE_SET_LENGTH(se, dm_segs->ds_len);
-                       tf = flags;
-                       if (seg ==  this_seg_lim - 1) {
+                       if (seg == this_seg_lim - 1) {
                                tf |=   MPI_SGE_FLAGS_LAST_ELEMENT;
                        }
                        if (seg == nseg - 1) {
@@ -1868,7 +1877,7 @@ bad:
 
        /*
         * Make up the rest of the data segments out of a chain element
-        * (contiained in the current request frame) which points to
+        * (contained in the current request frame) which points to
         * SIMPLE32 elements in the next request frame, possibly ending
         * with *another* chain element (if there's more).
         */
@@ -1904,7 +1913,7 @@ bad:
                nxt_off += MPT_RQSL(mpt);
 
                /*
-                * Now initialized the chain descriptor.
+                * Now initialize the chain descriptor.
                 */
                memset(ce, 0, sizeof (*ce));
 
@@ -1958,7 +1967,7 @@ bad:
 
                        MPI_pSGE_SET_LENGTH(se, dm_segs->ds_len);
                        tf = flags;
-                       if (seg ==  this_seg_lim - 1) {
+                       if (seg == this_seg_lim - 1) {
                                tf |=   MPI_SGE_FLAGS_LAST_ELEMENT;
                        }
                        if (seg == nseg - 1) {

Modified: head/sys/dev/mpt/mpt_pci.c
==============================================================================
--- head/sys/dev/mpt/mpt_pci.c  Sat Feb 11 11:34:53 2012        (r231517)
+++ head/sys/dev/mpt/mpt_pci.c  Sat Feb 11 12:03:44 2012        (r231518)
@@ -438,6 +438,10 @@ mpt_pci_attach(device_t dev)
        case PCI_PRODUCT_LSI_FC7X04X:
                mpt->is_fc = 1;
                break;
+       case PCI_PRODUCT_LSI_SAS1078:
+       case PCI_PRODUCT_LSI_SAS1078DE:
+               mpt->is_1078 = 1;
+               /* FALLTHROUGH */
        case PCI_PRODUCT_LSI_SAS1064:
        case PCI_PRODUCT_LSI_SAS1064A:
        case PCI_PRODUCT_LSI_SAS1064E:
@@ -445,8 +449,6 @@ mpt_pci_attach(device_t dev)
        case PCI_PRODUCT_LSI_SAS1066E:
        case PCI_PRODUCT_LSI_SAS1068:
        case PCI_PRODUCT_LSI_SAS1068E:
-       case PCI_PRODUCT_LSI_SAS1078:
-       case PCI_PRODUCT_LSI_SAS1078DE:
                mpt->is_sas = 1;
                break;
        default:
@@ -527,23 +529,31 @@ mpt_pci_attach(device_t dev)
        mpt->pci_pio_reg = bus_alloc_resource_any(dev, SYS_RES_IOPORT,
            &mpt_io_bar, RF_ACTIVE);
        if (mpt->pci_pio_reg == NULL) {
-               device_printf(dev, "unable to map registers in PIO mode\n");
-               goto bad;
+               if (bootverbose) {
+                       device_printf(dev,
+                           "unable to map registers in PIO mode\n");
+               }
+       } else {
+               mpt->pci_pio_st = rman_get_bustag(mpt->pci_pio_reg);
+               mpt->pci_pio_sh = rman_get_bushandle(mpt->pci_pio_reg);
        }
-       mpt->pci_pio_st = rman_get_bustag(mpt->pci_pio_reg);
-       mpt->pci_pio_sh = rman_get_bushandle(mpt->pci_pio_reg);
 
        /* Allocate kernel virtual memory for the 9x9's Mem0 region */
        mpt_mem_bar = PCIR_BAR(mpt_mem_bar);
        mpt->pci_reg = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
            &mpt_mem_bar, RF_ACTIVE);
        if (mpt->pci_reg == NULL) {
-               device_printf(dev, "Unable to memory map registers.\n");
-               if (mpt->is_sas) {
+               if (bootverbose || mpt->is_sas || mpt->pci_pio_reg == NULL) {
+                       device_printf(dev,
+                           "Unable to memory map registers.\n");
+               }
+               if (mpt->is_sas || mpt->pci_pio_reg == NULL) {
                        device_printf(dev, "Giving Up.\n");
                        goto bad;
                }
-               device_printf(dev, "Falling back to PIO mode.\n");
+               if (bootverbose) {
+                       device_printf(dev, "Falling back to PIO mode.\n");
+               }
                mpt->pci_st = mpt->pci_pio_st;
                mpt->pci_sh = mpt->pci_pio_sh;
        } else {

Modified: head/sys/dev/mpt/mpt_reg.h
==============================================================================
--- head/sys/dev/mpt/mpt_reg.h  Sat Feb 11 11:34:53 2012        (r231517)
+++ head/sys/dev/mpt/mpt_reg.h  Sat Feb 11 12:03:44 2012        (r231518)
@@ -77,6 +77,7 @@
 #define        MPT_OFFSET_REPLY_Q      0x44
 #define        MPT_OFFSET_HOST_INDEX   0x50
 #define        MPT_OFFSET_FUBAR        0x90
+#define        MPT_OFFSET_RESET_1078   0x10fc
 
 /* Bit Maps for DOORBELL register */
 enum DB_STATE_BITS {
_______________________________________________
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