Print this page
Fix identifying 2308 cards
Add support for more than 8 MSI-X interrupts.
Tidy up interrupt assignement and card ID messages.
Added code to support using MSI-X interrupts across multiple
reply queues. Not tested with anything other than 3008 yet.
Use MSI-X interrupts, just one for now.
Pre-allocate array for request sense buffers, similar to command frames.
No more messing about with scsi_alloc_consistent_buf().
Initial modifications using the code changes present between
the LSI source code for FreeBSD drivers. Specifically the changes
between from mpslsi-source-17.00.00.00 -> mpslsi-source-03.00.00.00.
This mainly involves using a different scatter/gather element in
frame setup.
Changes to enable driver to compile.
Header paths, object lists, etc.

Split Close
Expand all
Collapse all
          --- old/usr/src/uts/common/io/scsi/adapters/mpt_sas3/mptsas3_init.c
          +++ new/usr/src/uts/common/io/scsi/adapters/mpt_sas3/mptsas3_init.c
↓ open down ↓ 14 lines elided ↑ open up ↑
  15   15   * If applicable, add the following below this CDDL HEADER, with the
  16   16   * fields enclosed by brackets "[]" replaced with your own identifying
  17   17   * information: Portions Copyright [yyyy] [name of copyright owner]
  18   18   *
  19   19   * CDDL HEADER END
  20   20   */
  21   21  
  22   22  /*
  23   23   * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  24   24   * Use is subject to license terms.
       25 + * Copyright (c) 2014, Tegile Systems Inc. All rights reserved.
  25   26   */
  26   27  
  27   28  /*
  28   29   * Copyright (c) 2000 to 2009, LSI Corporation.
  29   30   * All rights reserved.
  30   31   *
  31   32   * Redistribution and use in source and binary forms of all code within
  32   33   * this file that is exclusively owned by LSI, with or without
  33   34   * modification, is permitted provided that, in addition to the CDDL 1.0
  34   35   * License requirements, the following conditions are met:
↓ open down ↓ 25 lines elided ↑ open up ↑
  60   61  #define MPTSAS_DEBUG
  61   62  #endif
  62   63  
  63   64  /*
  64   65   * standard header files
  65   66   */
  66   67  #include <sys/note.h>
  67   68  #include <sys/scsi/scsi.h>
  68   69  
  69   70  #pragma pack(1)
  70      -#include <sys/scsi/adapters/mpt_sas/mpi/mpi2_type.h>
  71      -#include <sys/scsi/adapters/mpt_sas/mpi/mpi2.h>
  72      -#include <sys/scsi/adapters/mpt_sas/mpi/mpi2_cnfg.h>
  73      -#include <sys/scsi/adapters/mpt_sas/mpi/mpi2_init.h>
  74      -#include <sys/scsi/adapters/mpt_sas/mpi/mpi2_ioc.h>
  75      -#include <sys/scsi/adapters/mpt_sas/mpi/mpi2_tool.h>
       71 +#include <sys/scsi/adapters/mpt_sas3/mpi/mpi2_type.h>
       72 +#include <sys/scsi/adapters/mpt_sas3/mpi/mpi2.h>
       73 +#include <sys/scsi/adapters/mpt_sas3/mpi/mpi2_cnfg.h>
       74 +#include <sys/scsi/adapters/mpt_sas3/mpi/mpi2_init.h>
       75 +#include <sys/scsi/adapters/mpt_sas3/mpi/mpi2_ioc.h>
       76 +#include <sys/scsi/adapters/mpt_sas3/mpi/mpi2_tool.h>
  76   77  #pragma pack()
  77   78  /*
  78   79   * private header files.
  79   80   */
  80      -#include <sys/scsi/adapters/mpt_sas/mptsas_var.h>
       81 +#include <sys/scsi/adapters/mpt_sas3/mptsas3_var.h>
  81   82  
  82   83  static int mptsas_ioc_do_get_facts(mptsas_t *mpt, caddr_t memp, int var,
  83   84          ddi_acc_handle_t accessp);
  84   85  static int mptsas_ioc_do_get_facts_reply(mptsas_t *mpt, caddr_t memp, int var,
  85   86          ddi_acc_handle_t accessp);
  86   87  static int mptsas_ioc_do_get_port_facts(mptsas_t *mpt, caddr_t memp, int var,
  87   88          ddi_acc_handle_t accessp);
  88   89  static int mptsas_ioc_do_get_port_facts_reply(mptsas_t *mpt, caddr_t memp,
  89   90      int var, ddi_acc_handle_t accessp);
  90   91  static int mptsas_ioc_do_enable_port(mptsas_t *mpt, caddr_t memp, int var,
↓ open down ↓ 3 lines elided ↑ open up ↑
  94   95  static int mptsas_ioc_do_enable_event_notification(mptsas_t *mpt, caddr_t memp,
  95   96          int var, ddi_acc_handle_t accessp);
  96   97  static int mptsas_ioc_do_enable_event_notification_reply(mptsas_t *mpt,
  97   98      caddr_t memp, int var, ddi_acc_handle_t accessp);
  98   99  static int mptsas_do_ioc_init(mptsas_t *mpt, caddr_t memp, int var,
  99  100          ddi_acc_handle_t accessp);
 100  101  static int mptsas_do_ioc_init_reply(mptsas_t *mpt, caddr_t memp, int var,
 101  102          ddi_acc_handle_t accessp);
 102  103  
 103  104  static const char *
 104      -mptsas_product_type_string(mptsas_t *mpt)
      105 +mptsas_devid_type_string(mptsas_t *mpt)
 105  106  {
 106      -        switch (mpt->m_productid & MPI2_FW_HEADER_PID_PROD_MASK) {
 107      -
 108      -        case MPI2_FW_HEADER_PID_PROD_A:
 109      -                return ("A");
      107 +        switch (mpt->m_devid) {
      108 +        case MPI2_MFGPAGE_DEVID_SAS2008:
      109 +                return ("SAS2008");
      110 +        case MPI2_MFGPAGE_DEVID_SAS2004:
      111 +                return ("SAS2004");
      112 +        case MPI2_MFGPAGE_DEVID_SAS2108_1:
      113 +        case MPI2_MFGPAGE_DEVID_SAS2108_2:
      114 +        case MPI2_MFGPAGE_DEVID_SAS2108_3:
      115 +                return ("SAS2108");
      116 +        case MPI2_MFGPAGE_DEVID_SAS2116_1:
      117 +        case MPI2_MFGPAGE_DEVID_SAS2116_2:
      118 +                return ("SAS2116");
      119 +        case MPI2_MFGPAGE_DEVID_SAS2208_1:
      120 +        case MPI2_MFGPAGE_DEVID_SAS2208_2:
      121 +        case MPI2_MFGPAGE_DEVID_SAS2208_3:
      122 +        case MPI2_MFGPAGE_DEVID_SAS2208_4:
      123 +        case MPI2_MFGPAGE_DEVID_SAS2208_5:
      124 +        case MPI2_MFGPAGE_DEVID_SAS2208_6:
      125 +#if 0
      126 +        /* These are the same as the next 2?? */
      127 +        case MPI2_MFGPAGE_DEVID_SAS2208_7:
      128 +        case MPI2_MFGPAGE_DEVID_SAS2208_8:
      129 +#endif
      130 +                return ("SAS2208");
      131 +        case MPI2_MFGPAGE_DEVID_SAS2308_1:
      132 +        case MPI2_MFGPAGE_DEVID_SAS2308_2:
      133 +        case MPI2_MFGPAGE_DEVID_SAS2308_3:
      134 +                return ("SAS2308");
      135 +        case MPI25_MFGPAGE_DEVID_SAS3004:
      136 +                return ("SAS3004");
      137 +        case MPI25_MFGPAGE_DEVID_SAS3008:
      138 +                return ("SAS3008");
      139 +        case MPI25_MFGPAGE_DEVID_SAS3108_1:
      140 +        case MPI25_MFGPAGE_DEVID_SAS3108_2:
      141 +        case MPI25_MFGPAGE_DEVID_SAS3108_3:
      142 +        case MPI25_MFGPAGE_DEVID_SAS3108_4:
      143 +        case MPI25_MFGPAGE_DEVID_SAS3108_5:
      144 +        case MPI25_MFGPAGE_DEVID_SAS3108_6:
      145 +                return ("SAS3108");
 110  146          default:
 111  147                  return ("?");
 112  148          }
 113  149  }
 114  150  
 115  151  int
 116  152  mptsas_ioc_get_facts(mptsas_t *mpt)
 117  153  {
 118  154          /*
 119  155           * Send get facts messages
↓ open down ↓ 49 lines elided ↑ open up ↑
 169  205  
 170  206          pMpi2IOCFactsReply_t    factsreply;
 171  207          int                     numbytes;
 172  208          uint_t                  iocstatus;
 173  209          char                    buf[32];
 174  210          uint16_t                numReplyFrames;
 175  211          uint16_t                queueSize, queueDiff;
 176  212          int                     simple_sge_main;
 177  213          int                     simple_sge_next;
 178  214          uint32_t                capabilities;
      215 +        uint16_t                msgversion;
 179  216  
 180  217          bzero(memp, sizeof (*factsreply));
 181  218          factsreply = (void *)memp;
 182  219          numbytes = sizeof (*factsreply);
 183  220  
 184  221          /*
 185  222           * get ioc facts reply message
 186  223           */
 187  224          if (mptsas_get_handshake_msg(mpt, memp, numbytes, accessp)) {
 188  225                  return (DDI_FAILURE);
↓ open down ↓ 11 lines elided ↑ open up ↑
 200  237           */
 201  238          mpt->m_fwversion = ddi_get32(accessp, &factsreply->FWVersion.Word);
 202  239          mpt->m_productid = ddi_get16(accessp, &factsreply->ProductID);
 203  240  
 204  241  
 205  242          (void) sprintf(buf, "%u.%u.%u.%u",
 206  243              ddi_get8(accessp, &factsreply->FWVersion.Struct.Major),
 207  244              ddi_get8(accessp, &factsreply->FWVersion.Struct.Minor),
 208  245              ddi_get8(accessp, &factsreply->FWVersion.Struct.Unit),
 209  246              ddi_get8(accessp, &factsreply->FWVersion.Struct.Dev));
 210      -        mptsas_log(mpt, CE_NOTE, "?mpt%d Firmware version v%s (%s)\n",
 211      -            mpt->m_instance, buf, mptsas_product_type_string(mpt));
      247 +        mptsas_log(mpt, CE_NOTE, "?MPT Firmware version v%s (%s)\n",
      248 +            buf, mptsas_devid_type_string(mpt));
 212  249          (void) ddi_prop_update_string(DDI_DEV_T_NONE, mpt->m_dip,
 213  250              "firmware-version", buf);
 214  251  
 215  252          /*
 216  253           * Set up request info.
 217  254           */
 218  255          mpt->m_max_requests = ddi_get16(accessp,
 219  256              &factsreply->RequestCredit) - 1;
 220  257          mpt->m_req_frame_size = ddi_get16(accessp,
 221  258              &factsreply->IOCRequestFrameSize) * 4;
↓ open down ↓ 16 lines elided ↑ open up ↑
 238  275          mpt->m_free_queue_depth = queueSize;
 239  276  
 240  277          /*
 241  278           * Size of reply descriptor post queue should be the number of
 242  279           * request frames + the number of reply frames + 1 and needs to
 243  280           * be a multiple of 16.  This size can be no larger than
 244  281           * MaxReplyDescriptorPostQueueDepth from IOCFacts.  If the
 245  282           * calculated queue size is larger than allowed, subtract a
 246  283           * multiple of 16 from m_max_requests, m_max_replies, and
 247  284           * m_reply_free_depth.
      285 +         *
      286 +         * There is no indication in the spec that you can reduce the
      287 +         * queue size if you have many.
 248  288           */
 249  289          queueSize = mpt->m_max_requests + numReplyFrames + 1;
 250  290          if (queueSize % 16) {
 251  291                  queueSize += 16 - (queueSize % 16);
 252  292          }
 253  293          mpt->m_post_queue_depth = ddi_get16(accessp,
 254  294              &factsreply->MaxReplyDescriptorPostQueueDepth);
 255  295          if (queueSize > mpt->m_post_queue_depth) {
 256  296                  queueDiff = queueSize - mpt->m_post_queue_depth;
 257  297                  if (queueDiff % 16) {
↓ open down ↓ 6 lines elided ↑ open up ↑
 264  304          }
 265  305          mpt->m_post_queue_depth = queueSize;
 266  306  
 267  307          /*
 268  308           * Set up max chain depth.
 269  309           */
 270  310          mpt->m_max_chain_depth = ddi_get8(accessp,
 271  311              &factsreply->MaxChainDepth);
 272  312          mpt->m_ioc_capabilities = ddi_get32(accessp,
 273  313              &factsreply->IOCCapabilities);
      314 +        if (mpt->m_ioc_capabilities & MPI2_IOCFACTS_CAPABILITY_MSI_X_INDEX) {
      315 +                mpt->m_max_msix_vectors = ddi_get8(accessp,
      316 +                    &factsreply->MaxMSIxVectors);
      317 +        }
      318 +
      319 +        /*
      320 +         * Set flag to check for SAS3 support.
      321 +         */
      322 +        msgversion = ddi_get16(accessp, &factsreply->MsgVersion);
      323 +        if (msgversion == MPI2_VERSION_02_05) {
      324 +                mptsas_log(mpt, CE_NOTE, "?mpt_sas3%d SAS 3 Supported\n",
      325 +                    mpt->m_instance);
      326 +                mpt->m_MPI25 = TRUE;
      327 +        } else {
      328 +                mptsas_log(mpt, CE_NOTE, "?mpt_sas3%d MPI Version 0x%x\n",
      329 +                    mpt->m_instance, msgversion);
      330 +        }
 274  331  
 275  332          /*
 276  333           * Calculate max frames per request based on DMA S/G length.
 277  334           */
 278  335          simple_sge_main = MPTSAS_MAX_FRAME_SGES64(mpt) - 1;
 279  336          simple_sge_next = mpt->m_req_frame_size /
 280      -            sizeof (MPI2_SGE_SIMPLE64) - 1;
      337 +            (mpt->m_MPI25 ? sizeof (MPI2_IEEE_SGE_SIMPLE64) :
      338 +            sizeof (MPI2_SGE_SIMPLE64)) - 1;
 281  339  
 282  340          mpt->m_max_request_frames = (MPTSAS_MAX_DMA_SEGS -
 283  341              simple_sge_main) / simple_sge_next + 1;
 284  342          if (((MPTSAS_MAX_DMA_SEGS - simple_sge_main) %
 285  343              simple_sge_next) > 1) {
 286  344                  mpt->m_max_request_frames++;
 287  345          }
 288  346  
 289  347          /*
 290  348           * Check if controller supports FW diag buffers and set flag to enable
 291  349           * each type.
 292  350           */
 293      -        capabilities = ddi_get32(accessp, &factsreply->IOCCapabilities);
      351 +        capabilities = mpt->m_ioc_capabilities;
 294  352          if (capabilities & MPI2_IOCFACTS_CAPABILITY_DIAG_TRACE_BUFFER) {
 295  353                  mpt->m_fw_diag_buffer_list[MPI2_DIAG_BUF_TYPE_TRACE].enabled =
 296  354                      TRUE;
 297  355          }
 298  356          if (capabilities & MPI2_IOCFACTS_CAPABILITY_SNAPSHOT_BUFFER) {
 299  357                  mpt->m_fw_diag_buffer_list[MPI2_DIAG_BUF_TYPE_SNAPSHOT].
 300  358                      enabled = TRUE;
 301  359          }
 302  360          if (capabilities & MPI2_IOCFACTS_CAPABILITY_EXTENDED_BUFFER) {
 303  361                  mpt->m_fw_diag_buffer_list[MPI2_DIAG_BUF_TYPE_EXTENDED].
↓ open down ↓ 292 lines elided ↑ open up ↑
 596  654          int                     numbytes;
 597  655          timespec_t              time;
 598  656          uint64_t                mSec;
 599  657  
 600  658          bzero(memp, sizeof (*init));
 601  659          init = (void *)memp;
 602  660          ddi_put8(accessp, &init->Function, MPI2_FUNCTION_IOC_INIT);
 603  661          ddi_put8(accessp, &init->WhoInit, MPI2_WHOINIT_HOST_DRIVER);
 604  662          ddi_put16(accessp, &init->MsgVersion, MPI2_VERSION);
 605  663          ddi_put16(accessp, &init->HeaderVersion, MPI2_HEADER_VERSION);
      664 +        if (mpt->m_intr_type == DDI_INTR_TYPE_MSIX) {
      665 +                ddi_put8(accessp, &init->HostMSIxVectors, mpt->m_intr_cnt);
      666 +        }
 606  667          ddi_put16(accessp, &init->SystemRequestFrameSize,
 607  668              mpt->m_req_frame_size / 4);
 608  669          ddi_put16(accessp, &init->ReplyDescriptorPostQueueDepth,
 609  670              mpt->m_post_queue_depth);
 610  671          ddi_put16(accessp, &init->ReplyFreeQueueDepth,
 611  672              mpt->m_free_queue_depth);
 612  673  
 613  674          /*
 614  675           * These addresses are set using the DMA cookie addresses from when the
 615  676           * memory was allocated.  Sense buffer hi address should be 0.
 616  677           */
 617      -        ddi_put32(accessp, &init->SenseBufferAddressHigh, 0);
      678 +        ddi_put32(accessp, &init->SenseBufferAddressHigh,
      679 +            (uint32_t)(mpt->m_req_sense_dma_addr >> 32));
 618  680          ddi_put32(accessp, &init->SystemReplyAddressHigh,
 619  681              (uint32_t)(mpt->m_reply_frame_dma_addr >> 32));
 620  682          ddi_put32(accessp, &init->SystemRequestFrameBaseAddress.High,
 621  683              (uint32_t)(mpt->m_req_frame_dma_addr >> 32));
 622  684          ddi_put32(accessp, &init->SystemRequestFrameBaseAddress.Low,
 623  685              (uint32_t)mpt->m_req_frame_dma_addr);
 624  686          ddi_put32(accessp, &init->ReplyDescriptorPostQueueAddress.High,
 625  687              (uint32_t)(mpt->m_post_queue_dma_addr >> 32));
 626  688          ddi_put32(accessp, &init->ReplyDescriptorPostQueueAddress.Low,
 627  689              (uint32_t)mpt->m_post_queue_dma_addr);
↓ open down ↓ 69 lines elided ↑ open up ↑
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX