6458733 si3124 sata HBA driver has arbitrary low number of scatter-gather entries affecting performance
authorxun ni - Sun Microsystems - Beijing China <Xun.Ni@Sun.COM>
Thu, 03 Jun 2010 10:07:17 +0800
changeset 12540 7b47bf378289
parent 12539 4762b6239106
child 12541 cf209463f3e9
6458733 si3124 sata HBA driver has arbitrary low number of scatter-gather entries affecting performance
usr/src/uts/common/io/sata/adapters/si3124/si3124.c
usr/src/uts/common/sys/sata/adapters/si3124/si3124reg.h
usr/src/uts/common/sys/sata/adapters/si3124/si3124var.h
--- a/usr/src/uts/common/io/sata/adapters/si3124/si3124.c	Wed Jun 02 16:25:47 2010 -0600
+++ b/usr/src/uts/common/io/sata/adapters/si3124/si3124.c	Thu Jun 03 10:07:17 2010 +0800
@@ -75,10 +75,13 @@
  *
  * external SGT tables: The external SGT tables pointed to from
  *	within si_prb_t are actually abstracted as si_sgblock_t. Each
- *	si_sgblock_t contains SI_MAX_SGT_TABLES_PER_PRB number of
- *	SGT tables linked in a chain. Currently this max value of
- *	SGT tables per block is hard coded as 10 which translates
- *	to a maximum of 31 dma cookies per single dma transfer.
+ *	si_sgblock_t contains si_dma_sg_number number of
+ *	SGT tables linked in a chain. Currently this default value of
+ *	SGT tables per block is at 85 as  which translates
+ *	to a maximum of 256 dma cookies per single dma transfer.
+ *	This value can be changed through the global var: si_dma_sg_number
+ *	in /etc/system, the maxium is at 21844 as which translates to 65535
+ *	dma cookies per single dma transfer.
  *
  *
  * III. Driver operation
@@ -342,7 +345,7 @@
 	1,			/* dma_attr_minxfer */
 	0xffffffffull,		/* dma_attr_maxxfer i.e. includes all cookies */
 	0xffffffffull,		/* dma_attr_seg */
-	SI_MAX_SGL_LENGTH,	/* dma_attr_sgllen */
+	SI_DEFAULT_SGL_LENGTH,	/* dma_attr_sgllen */
 	512,			/* dma_attr_granular */
 	0,			/* dma_attr_flags */
 };
@@ -422,6 +425,14 @@
 uint32_t si_debug_flags = 0x0;
 static int is_msi_supported = 0;
 
+/*
+ * The below global variables are tunable via /etc/system
+ *
+ * si_dma_sg_number
+ */
+
+int si_dma_sg_number = SI_DEFAULT_SGT_TABLES_PER_PRB;
+
 /* Opaque state pointer to be initialized by ddi_soft_state_init() */
 static void *si_statep	= NULL;
 
@@ -1033,6 +1044,16 @@
 
 	sata_hba_tran->sata_tran_hba_rev = SATA_TRAN_HBA_REV;
 	sata_hba_tran->sata_tran_hba_dip = si_ctlp->sictl_devinfop;
+
+	if (si_dma_sg_number > SI_MAX_SGT_TABLES_PER_PRB) {
+		si_dma_sg_number = SI_MAX_SGT_TABLES_PER_PRB;
+	} else if (si_dma_sg_number < SI_MIN_SGT_TABLES_PER_PRB) {
+		si_dma_sg_number = SI_MIN_SGT_TABLES_PER_PRB;
+	}
+
+	if (si_dma_sg_number != SI_DEFAULT_SGT_TABLES_PER_PRB) {
+		buffer_dma_attr.dma_attr_sgllen = SGE_LENGTH(si_dma_sg_number);
+	}
 	sata_hba_tran->sata_tran_hba_dma_attr = &buffer_dma_attr;
 
 	sata_hba_tran->sata_tran_hba_num_cports = si_ctlp->sictl_num_ports;
@@ -1961,7 +1982,8 @@
 {
 	si_port_state_t *si_portp;
 	uint_t cookie_count;
-	size_t incore_sgbpool_size = SI_NUM_SLOTS * sizeof (si_sgblock_t);
+	size_t incore_sgbpool_size = SI_NUM_SLOTS * sizeof (si_sgblock_t)
+	    * si_dma_sg_number;
 	size_t ret_len;
 	ddi_dma_cookie_t sgbpool_dma_cookie;
 
@@ -2615,7 +2637,7 @@
 		if (spkt->satapkt_cmd.satacmd_num_dma_cookies) {
 			prb->prb_sge1.sge_addr =
 			    si_portp->siport_sgbpool_physaddr +
-			    slot*sizeof (si_sgblock_t);
+			    slot * sizeof (si_sgblock_t) * si_dma_sg_number;
 			SET_SGE_LNK(prb->prb_sge1);
 		} else {
 			SET_SGE_TRM(prb->prb_sge1);
@@ -2625,7 +2647,7 @@
 		if (spkt->satapkt_cmd.satacmd_num_dma_cookies) {
 			prb->prb_sge0.sge_addr =
 			    si_portp->siport_sgbpool_physaddr +
-			    slot*sizeof (si_sgblock_t);
+			    slot * sizeof (si_sgblock_t) * si_dma_sg_number;
 			SET_SGE_LNK(prb->prb_sge0);
 
 		} else {
@@ -2635,14 +2657,15 @@
 		/* sge1 is left empty in non-ATAPI case */
 	}
 
-	bzero(&si_portp->siport_sgbpool[slot], sizeof (si_sgblock_t));
+	bzero(&si_portp->siport_sgbpool[slot * si_dma_sg_number],
+	    sizeof (si_sgblock_t) * si_dma_sg_number);
 
 	ncookies = spkt->satapkt_cmd.satacmd_num_dma_cookies;
-	ASSERT(ncookies <= SI_MAX_SGL_LENGTH);
+	ASSERT(ncookies <= (SGE_LENGTH(si_dma_sg_number)));
 
 	SIDBG1(SIDBG_COOKIES, si_ctlp, "total ncookies: %d", ncookies);
 	if (ncookies == 0) {
-		sgbp = &si_portp->siport_sgbpool[slot];
+		sgbp = &si_portp->siport_sgbpool[slot * si_dma_sg_number];
 		sgtp = &sgbp->sgb_sgt[0];
 		sgep = &sgtp->sgt_sge[0];
 
@@ -2657,10 +2680,11 @@
 		goto sgl_fill_done;
 	}
 
-	for (i = 0, cookie_index = 0, sgbp = &si_portp->siport_sgbpool[slot];
-	    i < SI_MAX_SGT_TABLES_PER_PRB; i++) {
-
-		sgtp = &sgbp->sgb_sgt[i];
+	for (i = 0, cookie_index = 0,
+	    sgbp = &si_portp->siport_sgbpool[slot * si_dma_sg_number];
+	    i < si_dma_sg_number; i++) {
+
+		sgtp = &sgbp->sgb_sgt[0] + i;
 
 		/* Now fill the first 3 entries of SGT in the loop below. */
 		for (j = 0, sgep = &sgtp->sgt_sge[0];
@@ -2708,7 +2732,7 @@
 			    cookie_index,
 			    ncookies);
 			sgep->sge_addr = si_portp->siport_sgbpool_physaddr +
-			    slot * sizeof (si_sgblock_t) +
+			    slot * sizeof (si_sgblock_t) * si_dma_sg_number +
 			    (i+1) * sizeof (si_sgt_t);
 
 			SET_SGE_LNK((*sgep));
@@ -2783,8 +2807,9 @@
 			    "si_deliver_satpkt sgt: low, high, count link");
 			for (j = 0,
 			    tmpsgep = (si_sge_t *)
-			    &si_portp->siport_sgbpool[slot];
-			    j < (sizeof (si_sgblock_t)/ sizeof (si_sge_t));
+			    &si_portp->siport_sgbpool[slot * si_dma_sg_number];
+			    j < (sizeof (si_sgblock_t)/ sizeof (si_sge_t))
+			    *si_dma_sg_number;
 			    j++, tmpsgep++) {
 				ptr = (int *)(void *)tmpsgep;
 				cmn_err(CE_WARN, "%x %x %x %x",
--- a/usr/src/uts/common/sys/sata/adapters/si3124/si3124reg.h	Wed Jun 02 16:25:47 2010 -0600
+++ b/usr/src/uts/common/sys/sata/adapters/si3124/si3124reg.h	Thu Jun 03 10:07:17 2010 +0800
@@ -297,8 +297,8 @@
 			DDI_DMA_SYNC_FORDEV);				  \
 									  \
 	(void) ddi_dma_sync(si_portp->siport_sgbpool_dma_handle,	  \
-			slot * sizeof (si_sgblock_t),			  \
-			sizeof (si_sgblock_t),				  \
+			slot * sizeof (si_sgblock_t) * si_dma_sg_number,  \
+			sizeof (si_sgblock_t) * si_dma_sg_number,	  \
 			DDI_DMA_SYNC_FORDEV);				  \
 									  \
 	ddi_put64(si_ctlp->sictl_port_acc_handle, 			  \
--- a/usr/src/uts/common/sys/sata/adapters/si3124/si3124var.h	Wed Jun 02 16:25:47 2010 -0600
+++ b/usr/src/uts/common/sys/sata/adapters/si3124/si3124var.h	Thu Jun 03 10:07:17 2010 +0800
@@ -38,17 +38,19 @@
 #define	SI_TIMEOUT			(1)	/* timed out */
 #define	SI_FAILURE			(-1)	/* unsuccessful return */
 
-#define	SI_MAX_SGT_TABLES_PER_PRB	10
-
+#define	SI_MAX_SGT_TABLES_PER_PRB	21844
+#define	SI_DEFAULT_SGT_TABLES_PER_PRB	85
+#define	SI_MIN_SGT_TABLES_PER_PRB	1
 /*
  * While the si_sge_t and si_sgt_t correspond to the actual SGE and SGT
  * definitions as per the datasheet, the si_sgblock_t (i.e scatter gather
- * block) is a logical data structure which holds multiple SGT tables.
- * The idea is to use multiple chained SGT tables per each PRB request.
+ * block) is a logical data structure which can hold dynamic SGEs and it
+ * is tunable through global variables /etc/system si3124:si_dma_sg_number.
+ * The idea is to use multiple tunable chained SGT tables per each PRB request.
  */
 
 typedef struct si_sgblock {
-	si_sgt_t sgb_sgt[SI_MAX_SGT_TABLES_PER_PRB];
+	si_sgt_t sgb_sgt[1];
 } si_sgblock_t;
 
 /*
@@ -58,7 +60,8 @@
  * SGT in the chain can host all the 4 entries since it does not need to
  * link any more.
  */
-#define	SI_MAX_SGL_LENGTH	(3*SI_MAX_SGT_TABLES_PER_PRB)+1
+#define	SGE_LENGTH(x)	(3*(x)+1)
+#define	SI_DEFAULT_SGL_LENGTH	SGE_LENGTH(SI_DEFAULT_SGT_TABLES_PER_PRB)
 
 typedef struct si_portmult_state {
 	int sipm_num_ports;