Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 8 Oct 2014 09:34:26 +0000 (UTC)
From:      Kashyap D Desai <kadesai@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r272739 - head/sys/dev/mrsas
Message-ID:  <201410080934.s989YQqV077228@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: kadesai
Date: Wed Oct  8 09:34:25 2014
New Revision: 272739
URL: https://svnweb.freebsd.org/changeset/base/272739

Log:
  Extended MSI-x vectors support for Invader and Fury(12Gb/s HBA).
  
  This Driver will create multiple MSI-x vector depending upon what FW expose.
  As of now 12 Gbp/s MR controller (Invader and Fury) expose 96 msix vector.
  As of now 6 Gbp/s MR controller (Thunderbolt) expose 16 msix vector.
  
  Reviewed by:	ambrisko
  MFC after:		2 weeks
  Sponsored by:	AVAGO Technologies

Modified:
  head/sys/dev/mrsas/mrsas.c
  head/sys/dev/mrsas/mrsas.h
  head/sys/dev/mrsas/mrsas_cam.c

Modified: head/sys/dev/mrsas/mrsas.c
==============================================================================
--- head/sys/dev/mrsas/mrsas.c	Wed Oct  8 09:30:35 2014	(r272738)
+++ head/sys/dev/mrsas/mrsas.c	Wed Oct  8 09:34:25 2014	(r272739)
@@ -54,6 +54,7 @@ __FBSDID("$FreeBSD$");
 #include <sys/types.h>
 #include <sys/kthread.h>
 #include <sys/taskqueue.h>
+#include <sys/smp.h>
 
 
 /* 
@@ -67,6 +68,8 @@ static d_ioctl_t    mrsas_ioctl;
 
 static struct mrsas_mgmt_info mrsas_mgmt_info;
 static struct mrsas_ident *mrsas_find_ident(device_t);
+static int mrsas_setup_msix(struct mrsas_softc *sc);
+static int mrsas_allocate_msix(struct mrsas_softc *sc);
 static void mrsas_shutdown_ctlr(struct mrsas_softc *sc, u_int32_t opcode);
 static void mrsas_flush_cache(struct mrsas_softc *sc);
 static void mrsas_reset_reply_desc(struct mrsas_softc *sc);
@@ -80,7 +83,7 @@ static int mrsas_setup_irq(struct mrsas_
 static int mrsas_alloc_mem(struct mrsas_softc *sc);
 static int mrsas_init_fw(struct mrsas_softc *sc);
 static int mrsas_setup_raidmap(struct mrsas_softc *sc);
-static int mrsas_complete_cmd(struct mrsas_softc *sc);
+static int mrsas_complete_cmd(struct mrsas_softc *sc, u_int32_t MSIxIndex);
 static int mrsas_clear_intr(struct mrsas_softc *sc);
 static int mrsas_get_ctrl_info(struct mrsas_softc *sc, 
                           struct mrsas_ctrl_info *ctrl_info);
@@ -151,7 +154,6 @@ static int mrsas_alloc_evt_log_info_cmd(
 static void mrsas_free_evt_log_info_cmd(struct mrsas_softc *sc);
 SYSCTL_NODE(_hw, OID_AUTO, mrsas, CTLFLAG_RD, 0, "MRSAS Driver Parameters");
 
-
 /**
  * PCI device struct and table
  *
@@ -709,9 +711,64 @@ static int mrsas_start_aen(struct mrsas_
 
 	return mrsas_register_aen(sc, eli.newest_seq_num + 1,
 				class_locale.word);
+
 }
 
 /**
+ * mrsas_setup_msix:	Allocate MSI-x vectors
+ * @sc:					Adapter soft state
+ */
+static int mrsas_setup_msix(struct mrsas_softc *sc)
+{
+	int i;
+	for (i = 0; i < sc->msix_vectors; i++) {
+		sc->irq_context[i].sc = sc;
+        sc->irq_context[i].MSIxIndex = i;
+		sc->irq_id[i] = i + 1;
+		sc->mrsas_irq[i] = bus_alloc_resource_any
+			(sc->mrsas_dev, SYS_RES_IRQ, &sc->irq_id[i]
+			 , RF_ACTIVE);
+		if (sc->mrsas_irq[i] == NULL) {
+			device_printf(sc->mrsas_dev, "Can't allocate MSI-x\n");
+			goto irq_alloc_failed;
+		}
+		if (bus_setup_intr(sc->mrsas_dev,
+			sc->mrsas_irq[i],
+			INTR_MPSAFE|INTR_TYPE_CAM,
+			NULL, mrsas_isr, &sc->irq_context[i],
+			&sc->intr_handle[i])) {
+			device_printf(sc->mrsas_dev,
+				"Cannot set up MSI-x interrupt handler\n");
+			goto irq_alloc_failed;
+		}
+	}
+	return SUCCESS;
+
+irq_alloc_failed:
+	mrsas_teardown_intr(sc);
+	return (FAIL);
+}
+
+/**
+ * mrsas_allocate_msix:		Setup MSI-x vectors
+ * @sc:						Adapter soft state
+ */
+static int mrsas_allocate_msix(struct mrsas_softc *sc)
+{
+	if (pci_alloc_msix(sc->mrsas_dev, &sc->msix_vectors) == 0) {
+		device_printf(sc->mrsas_dev, "Using MSI-X with %d number"
+				" of vectors\n", sc->msix_vectors);
+	} else {
+		device_printf(sc->mrsas_dev, "MSI-x setup failed\n");
+		goto irq_alloc_failed;
+	}
+	return SUCCESS;
+
+irq_alloc_failed:
+	mrsas_teardown_intr(sc);
+	return (FAIL);
+}
+/**
  * mrsas_attach:            PCI entry point
  * input:                   device struct pointer 
  * 
@@ -784,6 +841,8 @@ static int mrsas_attach(device_t dev)
     sc->adprecovery = MRSAS_HBA_OPERATIONAL;
 	sc->UnevenSpanSupport = 0;
 
+    sc->msix_enable = 0;
+
     /* Initialize Firmware */
     if (mrsas_init_fw(sc) != SUCCESS) {
         goto attach_fail_fw;
@@ -794,6 +853,7 @@ static int mrsas_attach(device_t dev)
         goto attach_fail_cam;
     }
 
+
     /* Register IRQs */
     if (mrsas_setup_irq(sc) != SUCCESS) {
         goto attach_fail_irq;
@@ -838,7 +898,9 @@ attach_fail_irq:
 attach_fail_cam:
     mrsas_cam_detach(sc);
 attach_fail_fw:
-//attach_fail_raidmap:
+    /* if MSIX vector is allocated and FW Init FAILED then release MSIX */
+    if (sc->msix_enable == 1)
+		pci_release_msi(sc->mrsas_dev);
     mrsas_free_mem(sc);
     mtx_destroy(&sc->sim_lock);
     mtx_destroy(&sc->aen_lock);
@@ -1081,11 +1143,28 @@ void mrsas_free_mem(struct mrsas_softc *
  */
 void mrsas_teardown_intr(struct mrsas_softc *sc)
 {
-    if (sc->intr_handle)
-        bus_teardown_intr(sc->mrsas_dev, sc->mrsas_irq, sc->intr_handle);
-    if (sc->mrsas_irq != NULL)
-        bus_release_resource(sc->mrsas_dev, SYS_RES_IRQ, sc->irq_id, sc->mrsas_irq);
-    sc->intr_handle = NULL;
+    int i;
+    if (!sc->msix_enable) {
+	    if (sc->intr_handle[0])
+		bus_teardown_intr(sc->mrsas_dev, sc->mrsas_irq[0], sc->intr_handle[0]);
+	    if (sc->mrsas_irq[0] != NULL)
+		bus_release_resource(sc->mrsas_dev, SYS_RES_IRQ, sc->irq_id[0], sc->mrsas_irq[0]);
+	    sc->intr_handle[0] = NULL;
+    } else {
+		for (i = 0; i < sc->msix_vectors; i++) {
+			if (sc->intr_handle[i])
+				bus_teardown_intr(sc->mrsas_dev, sc->mrsas_irq[i],
+					sc->intr_handle[i]);
+
+			if (sc->mrsas_irq[i] != NULL)
+				bus_release_resource(sc->mrsas_dev, SYS_RES_IRQ,
+					sc->irq_id[i], sc->mrsas_irq[i]);
+
+			sc->intr_handle[i] = NULL;
+		}
+		pci_release_msi(sc->mrsas_dev);
+	}
+
 }
 
 /**
@@ -1195,19 +1274,29 @@ do_ioctl:
  */
 static int mrsas_setup_irq(struct mrsas_softc *sc)
 {
-    sc->irq_id = 0;
-    sc->mrsas_irq = bus_alloc_resource_any(sc->mrsas_dev, SYS_RES_IRQ,
-                        &sc->irq_id, RF_SHAREABLE | RF_ACTIVE);
-    if (sc->mrsas_irq == NULL){
-        device_printf(sc->mrsas_dev, "Cannot allocate interrupt\n");
-        return (FAIL);
-    }
-    if (bus_setup_intr(sc->mrsas_dev, sc->mrsas_irq, INTR_MPSAFE|INTR_TYPE_CAM,
-                       NULL, mrsas_isr, sc, &sc->intr_handle)) {
-        device_printf(sc->mrsas_dev, "Cannot set up interrupt\n");
-        return (FAIL);
-    }
+    if (sc->msix_enable && (mrsas_setup_msix(sc) == SUCCESS))
+		device_printf(sc->mrsas_dev, "MSI-x interrupts setup success\n");
 
+	else {
+			device_printf(sc->mrsas_dev, "Fall back to legacy interrupt\n");
+			sc->irq_context[0].sc = sc;
+			sc->irq_context[0].MSIxIndex = 0;
+			sc->irq_id[0] = 0;
+			sc->mrsas_irq[0] = bus_alloc_resource_any(sc->mrsas_dev,
+				SYS_RES_IRQ, &sc->irq_id[0], RF_SHAREABLE | RF_ACTIVE);
+			if (sc->mrsas_irq[0] == NULL){
+				device_printf(sc->mrsas_dev, "Cannot allocate legcay"
+					"interrupt\n");
+				return (FAIL);
+			}
+			if (bus_setup_intr(sc->mrsas_dev, sc->mrsas_irq[0],
+					INTR_MPSAFE|INTR_TYPE_CAM, NULL, mrsas_isr,
+					&sc->irq_context[0], &sc->intr_handle[0])) {
+					device_printf(sc->mrsas_dev, "Cannot set up legacy"
+						"interrupt\n");
+				return (FAIL);
+			}
+	}
     return (0);
 }
 
@@ -1221,16 +1310,16 @@ static int mrsas_setup_irq(struct mrsas_
  */
 void mrsas_isr(void *arg)
 {
-    struct mrsas_softc *sc = (struct mrsas_softc *)arg;
-    int status;
-
-    /* Clear FW state change interrupt */
-    status = mrsas_clear_intr(sc);
+    struct mrsas_irq_context *irq_context = (struct mrsas_irq_context *)arg;
+    struct mrsas_softc *sc = irq_context->sc;
+    int status = 0;
+
+	if (!sc->msix_vectors) {
+		status = mrsas_clear_intr(sc);
+			if (!status)
+				return;
+	}
 
-    /* Not our interrupt */
-    if (!status)
-        return;
-    
     /* If we are resetting, bail */
     if (test_bit(MRSAS_FUSION_IN_RESET, &sc->reset_flags)) {
         printf(" Entered into ISR when OCR is going active. \n");
@@ -1238,7 +1327,7 @@ void mrsas_isr(void *arg)
         return;
     }
     /* Process for reply request and clear response interrupt */
-    if (mrsas_complete_cmd(sc) != SUCCESS) 
+    if (mrsas_complete_cmd(sc, irq_context->MSIxIndex) != SUCCESS)
         mrsas_clear_intr(sc);
 
     return;
@@ -1255,7 +1344,7 @@ void mrsas_isr(void *arg)
  * the command type and perform the appropriate action.  Before we
  * return, we clear the response interrupt.
  */
-static int mrsas_complete_cmd(struct mrsas_softc *sc)
+static int mrsas_complete_cmd(struct mrsas_softc *sc, u_int32_t MSIxIndex)
 {
     Mpi2ReplyDescriptorsUnion_t *desc;
     MPI2_SCSI_IO_SUCCESS_REPLY_DESCRIPTOR *reply_desc;
@@ -1276,7 +1365,9 @@ static int mrsas_complete_cmd(struct mrs
         return (DONE);
 
     desc = sc->reply_desc_mem;
-    desc += sc->last_reply_idx;
+    //desc += sc->last_reply_idx[0];
+    desc += ((MSIxIndex * sc->reply_alloc_sz)/sizeof(MPI2_REPLY_DESCRIPTORS_UNION))
+               + sc->last_reply_idx[MSIxIndex];
 
     reply_desc = (MPI2_SCSI_IO_SUCCESS_REPLY_DESCRIPTOR *)desc;
 
@@ -1321,18 +1412,19 @@ static int mrsas_complete_cmd(struct mrs
                 break;
         }
 
-        sc->last_reply_idx++;
-        if (sc->last_reply_idx >= sc->reply_q_depth) 
-            sc->last_reply_idx = 0;
+        sc->last_reply_idx[MSIxIndex]++;
+        if (sc->last_reply_idx[MSIxIndex] >= sc->reply_q_depth)
+            sc->last_reply_idx[MSIxIndex] = 0;
 
         desc->Words = ~((uint64_t)0x00); /* set it back to all 0xFFFFFFFFs */
         num_completed++;
         threshold_reply_count++;
 
         /* Get the next reply descriptor */
-        if (!sc->last_reply_idx)
+        if (!sc->last_reply_idx[MSIxIndex]){
             desc = sc->reply_desc_mem;
-        else
+            desc += ((MSIxIndex * sc->reply_alloc_sz)/sizeof(MPI2_REPLY_DESCRIPTORS_UNION));
+        } else
             desc++;
 
         reply_desc = (MPI2_SCSI_IO_SUCCESS_REPLY_DESCRIPTOR *)desc;
@@ -1349,18 +1441,40 @@ static int mrsas_complete_cmd(struct mrs
          * completed.
          */
         if (threshold_reply_count >= THRESHOLD_REPLY_COUNT) {
-            mrsas_write_reg(sc, offsetof(mrsas_reg_set, reply_post_host_index),
-                            sc->last_reply_idx);
-            threshold_reply_count = 0;
+				if (sc->msix_enable) {
+					if ((sc->device_id == MRSAS_INVADER) ||
+						(sc->device_id == MRSAS_FURY))
+						mrsas_write_reg(sc, sc->msix_reg_offset[MSIxIndex/8],
+						   ((MSIxIndex & 0x7) << 24) |
+						   sc->last_reply_idx[MSIxIndex]);
+					 else
+						mrsas_write_reg(sc, sc->msix_reg_offset[0], (MSIxIndex << 24) |
+						   sc->last_reply_idx[MSIxIndex]);
+				 } else
+					mrsas_write_reg(sc, offsetof(mrsas_reg_set,
+					 reply_post_host_index),sc->last_reply_idx[0]);
+
+				 threshold_reply_count = 0;
+				}
         }
-    }
 
     /* No match, just return */
     if (num_completed == 0)
         return (DONE);
 
     /* Clear response interrupt */
-    mrsas_write_reg(sc, offsetof(mrsas_reg_set, reply_post_host_index),sc->last_reply_idx); 
+     if (sc->msix_enable) {
+	     if ((sc->device_id == MRSAS_INVADER) ||
+                    (sc->device_id == MRSAS_FURY)){
+		    mrsas_write_reg(sc, sc->msix_reg_offset[MSIxIndex/8],
+                       ((MSIxIndex & 0x7) << 24) |
+                       sc->last_reply_idx[MSIxIndex]);
+		} else
+		    mrsas_write_reg(sc, sc->msix_reg_offset[0], (MSIxIndex << 24) |
+                       sc->last_reply_idx[MSIxIndex]);
+     } else
+            mrsas_write_reg(sc, offsetof(mrsas_reg_set,
+                 reply_post_host_index),sc->last_reply_idx[0]);
 
     return(0);
 }
@@ -1423,7 +1537,7 @@ void mrsas_map_mpt_cmd_status(struct mrs
 static int mrsas_alloc_mem(struct mrsas_softc *sc)
 {
     u_int32_t verbuf_size, io_req_size, reply_desc_size, sense_size,
-              chain_frame_size, evt_detail_size;
+              chain_frame_size, evt_detail_size, count;
 
     /*
      * Allocate parent DMA tag
@@ -1537,10 +1651,11 @@ static int mrsas_alloc_mem(struct mrsas_
         return (ENOMEM);
     }
 
+    count = sc->msix_vectors > 0 ? sc->msix_vectors : 1;
     /*
      * Allocate Reply Descriptor Array
      */ 
-    reply_desc_size = sc->reply_alloc_sz; 
+    reply_desc_size = sc->reply_alloc_sz * count;
     if (bus_dma_tag_create( sc->mrsas_parent_tag,   // parent
                             16, 0,                   // algnmnt, boundary
                             BUS_SPACE_MAXADDR_32BIT,// lowaddr
@@ -1796,13 +1911,15 @@ ABORT:
  */
 static int mrsas_init_fw(struct mrsas_softc *sc)
 {
+
+    int ret, loop, ocr = 0;
     u_int32_t max_sectors_1;
     u_int32_t max_sectors_2;
     u_int32_t tmp_sectors;
     struct mrsas_ctrl_info *ctrl_info;
-
-    int ret, ocr = 0;
-
+    u_int32_t scratch_pad_2;
+    int msix_enable = 0;
+    int fw_msix_count = 0;
       
     /* Make sure Firmware is ready */
     ret = mrsas_transition_to_ready(sc, ocr);
@@ -1810,7 +1927,57 @@ static int mrsas_init_fw(struct mrsas_so
         return(ret);
 	}
 
-    /* Get operational params, sge flags, send init cmd to ctlr */
+
+    /* MSI-x index 0- reply post host index register */
+	sc->msix_reg_offset[0] = MPI2_REPLY_POST_HOST_INDEX_OFFSET;
+	/* Check if MSI-X is supported while in ready state */
+	msix_enable = (mrsas_read_reg(sc, offsetof(mrsas_reg_set, outbound_scratch_pad)) & 0x4000000) >> 0x1a;
+
+	if (msix_enable) {
+		scratch_pad_2 = mrsas_read_reg(sc, offsetof(mrsas_reg_set,
+			outbound_scratch_pad_2));
+
+		/* Check max MSI-X vectors */
+		if (sc->device_id == MRSAS_TBOLT) {
+			sc->msix_vectors = (scratch_pad_2
+				& MR_MAX_REPLY_QUEUES_OFFSET) + 1;
+			fw_msix_count = sc->msix_vectors;
+		} else {
+			/* Invader/Fury supports 96 MSI-X vectors */
+			sc->msix_vectors = ((scratch_pad_2
+				& MR_MAX_REPLY_QUEUES_EXT_OFFSET)
+				>> MR_MAX_REPLY_QUEUES_EXT_OFFSET_SHIFT) +				1;
+			fw_msix_count = sc->msix_vectors;
+
+			/* Save 1-15 reply post index address to local
+			 * memory
+			 * Index 0 is already saved from reg offset
+			 * MPI2_REPLY_POST_HOST_INDEX_OFFSET
+			 */
+			for (loop = 1; loop < MR_MAX_MSIX_REG_ARRAY;
+				loop++) {
+				sc->msix_reg_offset[loop] =
+				MPI2_SUP_REPLY_POST_HOST_INDEX_OFFSET +
+				(loop * 0x10);
+			}
+		}
+
+		/* Don't bother allocating more MSI-X vectors than cpus */
+		sc->msix_vectors = min(sc->msix_vectors,
+					 mp_ncpus);
+
+		/* Allocate MSI-x vectors */
+		if (mrsas_allocate_msix(sc) == SUCCESS)
+			sc->msix_enable = 1;
+		else
+			sc->msix_enable = 0;
+
+		device_printf(sc->mrsas_dev, "FW supports <%d> MSIX vector,"
+						"Online CPU %d Current MSIX <%d>\n",
+						fw_msix_count, mp_ncpus, sc->msix_vectors);
+	}
+
+	/* Get operational params, sge flags, send init cmd to ctlr */
     if (mrsas_init_adapter(sc) != SUCCESS){
         device_printf(sc->mrsas_dev, "Adapter initialize Fail.\n");
         return(1);
@@ -1907,6 +2074,7 @@ int mrsas_init_adapter(struct mrsas_soft
     uint32_t status;
     u_int32_t max_cmd;
     int ret;
+    int i = 0;
 
     /* Read FW status register */
     status = mrsas_read_reg(sc, offsetof(mrsas_reg_set, outbound_scratch_pad));
@@ -1919,7 +2087,7 @@ int mrsas_init_adapter(struct mrsas_soft
     max_cmd = sc->max_fw_cmds;
 
     /* Determine allocation size of command frames */
-    sc->reply_q_depth = ((max_cmd *2 +1 +15)/16*16);
+    sc->reply_q_depth = ((max_cmd +1 +15)/16*16);
     sc->request_alloc_sz = sizeof(MRSAS_REQUEST_DESCRIPTOR_UNION) * max_cmd;
     sc->reply_alloc_sz = sizeof(MPI2_REPLY_DESCRIPTORS_UNION) * (sc->reply_q_depth);
     sc->io_frames_alloc_sz = MRSAS_MPI2_RAID_DEFAULT_IO_FRAME_SIZE + (MRSAS_MPI2_RAID_DEFAULT_IO_FRAME_SIZE * (max_cmd + 1));
@@ -1936,7 +2104,9 @@ int mrsas_init_adapter(struct mrsas_soft
     sc->chain_offset_io_request = (MRSAS_MPI2_RAID_DEFAULT_IO_FRAME_SIZE - 
         sizeof(MPI2_SGE_IO_UNION))/16;
 
-    sc->last_reply_idx = 0;
+    int count = sc->msix_vectors > 0 ? sc->msix_vectors : 1;
+    for (i = 0 ; i < count; i++)
+		sc->last_reply_idx[i] = 0;
 
     ret = mrsas_alloc_mem(sc);
     if (ret != SUCCESS)
@@ -1949,6 +2119,7 @@ int mrsas_init_adapter(struct mrsas_soft
     ret = mrsas_ioc_init(sc);
     if (ret != SUCCESS)
         return(ret);
+
 	
     
     return(0);
@@ -2042,12 +2213,21 @@ int mrsas_ioc_init(struct mrsas_softc *s
     IOCInitMsg->ReplyDescriptorPostQueueDepth = sc->reply_q_depth;
     IOCInitMsg->ReplyDescriptorPostQueueAddress = sc->reply_desc_phys_addr;
     IOCInitMsg->SystemRequestFrameBaseAddress = sc->io_request_phys_addr;
+    IOCInitMsg->HostMSIxVectors = (sc->msix_vectors > 0 ? sc->msix_vectors : 0);
 
     init_frame = (struct mrsas_init_frame *)sc->ioc_init_mem;
     init_frame->cmd = MFI_CMD_INIT;
     init_frame->cmd_status = 0xFF;
     init_frame->flags |= MFI_FRAME_DONT_POST_IN_REPLY_QUEUE;
 
+    /* driver support Extended MSIX */
+    if ((sc->device_id == MRSAS_INVADER) ||
+         (sc->device_id == MRSAS_FURY)) {
+             init_frame->driver_operations.
+                mfi_capabilities.support_additional_msix = 1;
+    }
+
+
     if (sc->verbuf_mem) {
         snprintf((char *)sc->verbuf_mem, strlen(MRSAS_VERSION)+2,"%s\n",
                 MRSAS_VERSION);
@@ -2113,7 +2293,7 @@ int mrsas_ioc_init(struct mrsas_softc *s
 int mrsas_alloc_mpt_cmds(struct mrsas_softc *sc)
 {
     int i, j;
-    u_int32_t max_cmd;
+    u_int32_t max_cmd, count;
     struct mrsas_mpt_cmd *cmd;
     pMpi2ReplyDescriptorsUnion_t reply_desc;
     u_int32_t offset, chain_offset, sense_offset;
@@ -2183,7 +2363,8 @@ int mrsas_alloc_mpt_cmds(struct mrsas_so
     
     /* Initialize reply descriptor array to 0xFFFFFFFF */
     reply_desc = sc->reply_desc_mem;
-    for (i = 0; i < sc->reply_q_depth; i++, reply_desc++) {
+    count = sc->msix_vectors > 0 ? sc->msix_vectors : 1;
+    for (i = 0; i < sc->reply_q_depth * count ; i++, reply_desc++) {
         reply_desc->Words = MRSAS_ULONG_MAX;
     }
     return(0);
@@ -2400,11 +2581,14 @@ mrsas_ocr_thread(void *arg)
  */
 void  mrsas_reset_reply_desc(struct mrsas_softc *sc)
 {
-    int i;
+    int i, count;
     pMpi2ReplyDescriptorsUnion_t reply_desc;
 
-    sc->last_reply_idx = 0;
-    reply_desc = sc->reply_desc_mem;
+    count = sc->msix_vectors > 0 ? sc->msix_vectors : 1;
+    for (i = 0 ; i < count ; i++)
+		sc->last_reply_idx[i] = 0;
+
+	reply_desc = sc->reply_desc_mem;
     for (i = 0; i < sc->reply_q_depth; i++, reply_desc++) {
         reply_desc->Words = MRSAS_ULONG_MAX;
     }
@@ -2641,7 +2825,8 @@ void mrsas_kill_hba (struct mrsas_softc 
 int mrsas_wait_for_outstanding(struct mrsas_softc *sc)
 {
     int i, outstanding, retval = 0;
-    u_int32_t fw_state;
+    u_int32_t fw_state, count, MSIxIndex;
+
 
     for (i = 0; i < MRSAS_RESET_WAIT_TIME; i++) {
         if (sc->remove_in_progress) {
@@ -2666,7 +2851,9 @@ int mrsas_wait_for_outstanding(struct mr
         if (!(i % MRSAS_RESET_NOTICE_INTERVAL)) {
             mrsas_dprint(sc, MRSAS_OCR, "[%2d]waiting for %d "
                                 "commands to complete\n",i,outstanding);
-            mrsas_complete_cmd(sc);
+            count = sc->msix_vectors > 0 ? sc->msix_vectors : 1;
+            for (MSIxIndex = 0 ; MSIxIndex < count; MSIxIndex++)
+                  mrsas_complete_cmd(sc, MSIxIndex);
         }
         DELAY(1000 * 1000);
     }

Modified: head/sys/dev/mrsas/mrsas.h
==============================================================================
--- head/sys/dev/mrsas/mrsas.h	Wed Oct  8 09:30:35 2014	(r272738)
+++ head/sys/dev/mrsas/mrsas.h	Wed Oct  8 09:34:25 2014	(r272739)
@@ -110,6 +110,7 @@ __FBSDID("$FreeBSD$");
 #define MRSAS_IO_TIMEOUT 180000      /* 180 second timeout */
 #define MRSAS_LDIO_QUEUE_DEPTH   70  /* 70 percent as default */
 #define THRESHOLD_REPLY_COUNT 50
+#define MAX_MSIX_COUNT 128
 
 /* 
  Boolean types 
@@ -1959,6 +1960,16 @@ struct mrsas_ctrl_info {
 #define MRSAS_DEFAULT_CMD_TIMEOUT             90
 #define MRSAS_THROTTLE_QUEUE_DEPTH            16
 
+/*
+ * MSI-x regsiters offset defines
+ */
+#define MPI2_SUP_REPLY_POST_HOST_INDEX_OFFSET   (0x0000030C)
+#define MPI2_REPLY_POST_HOST_INDEX_OFFSET       (0x0000006C)
+#define MR_MAX_REPLY_QUEUES_OFFSET		(0x0000001F)
+#define MR_MAX_REPLY_QUEUES_EXT_OFFSET		(0x003FC000)
+#define MR_MAX_REPLY_QUEUES_EXT_OFFSET_SHIFT	14
+#define MR_MAX_MSIX_REG_ARRAY			16
+
 /* 
  * FW reports the maximum of number of commands that it can accept (maximum
  * commands that can be outstanding) at any time. The driver must report a
@@ -1968,7 +1979,7 @@ struct mrsas_ctrl_info {
  */
 #define MRSAS_INT_CMDS                        32
 #define MRSAS_SKINNY_INT_CMDS                 5
-#define MRSAS_MAX_MSIX_QUEUES                 16
+#define MRSAS_MAX_MSIX_QUEUES                 128
 
 /*
  * FW can accept both 32 and 64 bit SGLs. We want to allocate 32/64 bit
@@ -1993,6 +2004,17 @@ struct mrsas_ctrl_info {
 #define MFI_1068_FW_HANDSHAKE_OFFSET            0x64
 #define MFI_1068_FW_READY                       0xDDDD0000
 
+typedef union _MFI_CAPABILITIES {
+        struct {
+                u_int32_t     support_fp_remote_lun:1;
+                u_int32_t     support_additional_msix:1;
+                u_int32_t     support_fastpath_wb:1;
+                u_int32_t     support_max_255lds:1;
+                u_int32_t     reserved:28;
+        } mfi_capabilities;
+        u_int32_t     reg;
+} MFI_CAPABILITIES;
+
 #pragma pack(1)
 struct mrsas_sge32 {
     u_int32_t phys_addr;
@@ -2035,18 +2057,6 @@ struct mrsas_header {
 };
 #pragma pack()
 
-
-typedef union _MFI_CAPABILITIES {
-        struct {
-                u_int32_t     support_fp_remote_lun:1;
-                u_int32_t     support_additional_msix:1;
-                u_int32_t     support_fastpath_wb:1;
-                u_int32_t     support_max_255lds:1;
-                u_int32_t     reserved:28;
-        } mfi_capabilities;
-        u_int32_t     reg;
-} MFI_CAPABILITIES;
-
 #pragma pack(1)
 struct mrsas_init_frame {
     u_int8_t cmd;                 /*00h */
@@ -2162,8 +2172,7 @@ struct mrsas_abort_frame {
     u_int8_t cmd_status;          /*02h */
 
     u_int8_t reserved_1;          /*03h */
-    u_int32_t reserved_2;         /*04h */
-
+    MFI_CAPABILITIES driver_operations;  /*04h */
     u_int32_t context;            /*08h */
     u_int32_t pad_0;              /*0Ch */
 
@@ -2419,6 +2428,11 @@ struct mrsas_evt_detail {
 
 } __packed;
 
+struct mrsas_irq_context {
+        struct mrsas_softc *sc;
+        uint32_t MSIxIndex;
+};
+
 /* Controller management info added to support Linux Emulator */
 #define MAX_MGMT_ADAPTERS               1024
 
@@ -2479,9 +2493,13 @@ struct mrsas_softc {
     struct mtx aen_lock;                  // aen lock
     uint32_t           max_fw_cmds;       // Max commands from FW
     uint32_t           max_num_sge;       // Max number of SGEs
-    struct resource    *mrsas_irq;        // interrupt interface window
-    void               *intr_handle;      // handle
-    int                irq_id;            // intr resource id
+    struct resource    *mrsas_irq[MAX_MSIX_COUNT];        // interrupt interface window
+    void               *intr_handle[MAX_MSIX_COUNT];      // handle
+    int                irq_id[MAX_MSIX_COUNT];            // intr resource id
+    struct mrsas_irq_context irq_context[MAX_MSIX_COUNT];
+    int                msix_vectors;      // Max msix vectors
+    int                msix_enable;      // MSI-x support
+    uint32_t           msix_reg_offset[16];
     struct mrsas_mpt_cmd   **mpt_cmd_list;
     struct mrsas_mfi_cmd   **mfi_cmd_list;
     TAILQ_HEAD(, mrsas_mpt_cmd) mrsas_mpt_cmd_list_head;
@@ -2492,7 +2510,7 @@ struct mrsas_softc {
     bus_addr_t         io_request_frames_phys;
     u_int8_t           *io_request_frames;
     bus_addr_t         reply_frames_desc_phys;
-    u_int16_t          last_reply_idx;
+    u_int16_t          last_reply_idx[MAX_MSIX_COUNT];
     u_int32_t          reply_q_depth;
     u_int32_t          request_alloc_sz;
     u_int32_t          reply_alloc_sz;

Modified: head/sys/dev/mrsas/mrsas_cam.c
==============================================================================
--- head/sys/dev/mrsas/mrsas_cam.c	Wed Oct  8 09:30:35 2014	(r272738)
+++ head/sys/dev/mrsas/mrsas_cam.c	Wed Oct  8 09:34:25 2014	(r272739)
@@ -49,8 +49,14 @@ __FBSDID("$FreeBSD$");
 #include <cam/scsi/scsi_all.h>
 #include <cam/scsi/scsi_message.h>
 #include <sys/taskqueue.h>
+#include <sys/kernel.h>
 
 
+#include <sys/time.h> /* XXX for pcpu.h */
+#include <sys/pcpu.h> /* XXX for PCPU_GET */
+
+#define smp_processor_id()  PCPU_GET(cpuid)
+
 /*
  * Function prototypes
  */
@@ -794,7 +800,11 @@ int mrsas_setup_io(struct mrsas_softc *s
             fp_possible = io_info.fpOkForIo;
     }
 
-    if (fp_possible) {
+	cmd->request_desc->SCSIIO.MSIxIndex =
+		sc->msix_vectors ? smp_processor_id() % sc->msix_vectors : 0;
+
+
+	if (fp_possible) {
         mrsas_set_pd_lba(io_request, csio->cdb_len, &io_info, ccb, map_ptr, 
             start_lba_lo, ld_block_size);
         io_request->Function = MPI2_FUNCTION_SCSI_IO_REQUEST;
@@ -881,6 +891,9 @@ int mrsas_build_dcdb(struct mrsas_softc 
             MRSAS_REQ_DESCRIPT_FLAGS_TYPE_SHIFT);
         cmd->request_desc->SCSIIO.DevHandle = 
             map_ptr->raidMap.devHndlInfo[device_id].curDevHdl;
+		cmd->request_desc->SCSIIO.MSIxIndex =
+			sc->msix_vectors ? smp_processor_id() % sc->msix_vectors : 0;
+
     }
     else {
         io_request->Function  = MRSAS_MPI2_FUNCTION_LD_IO_REQUEST;



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201410080934.s989YQqV077228>