changeset 2553:624f674f2ad8

6430966 SATA NCQ support is needed in SATA framework and hba drivers 6460173 sata module is not warlock clean
author ls24207
date Tue, 15 Aug 2006 15:13:46 -0700
parents 04b007b7b43f
children 026db43c8acc
files usr/src/uts/common/io/sata/impl/sata.c usr/src/uts/common/sys/sata/sata_defs.h usr/src/uts/common/sys/sata/sata_hba.h
diffstat 3 files changed, 135 insertions(+), 45 deletions(-) [+]
line wrap: on
line diff
--- a/usr/src/uts/common/io/sata/impl/sata.c	Tue Aug 15 14:28:22 2006 -0700
+++ b/usr/src/uts/common/io/sata/impl/sata.c	Tue Aug 15 15:13:46 2006 -0700
@@ -63,7 +63,8 @@
 #define	SATA_ENABLE_QUEUING		1
 #define	SATA_ENABLE_NCQ			2
 #define	SATA_ENABLE_PROCESS_EVENTS	4
-int sata_func_enable = SATA_ENABLE_PROCESS_EVENTS | SATA_ENABLE_QUEUING;
+int sata_func_enable =
+	SATA_ENABLE_PROCESS_EVENTS | SATA_ENABLE_QUEUING | SATA_ENABLE_NCQ;
 
 #ifdef SATA_DEBUG
 #define	SATA_LOG_D(args)	sata_log args
@@ -321,6 +322,32 @@
 static 	int sata_event_thread_active = 0;
 extern 	pri_t minclsyspri;
 
+/*
+ * NCQ specific data
+ */
+static const sata_cmd_t sata_rle_cmd = {
+	SATA_CMD_REV,
+	NULL,
+	{
+		SATA_DIR_READ
+	},
+	ATA_ADDR_LBA48,
+	0,
+	0,
+	0,
+	0,
+	0,
+	1,
+	READ_LOG_EXT_NCQ_ERROR_RECOVERY,
+	0,
+	0,
+	0,
+	SATAC_READ_LOG_EXT,
+	0,
+	0,
+	0,
+};
+
 /* Warlock directives */
 
 _NOTE(SCHEME_PROTECTS_DATA("No Mutex Needed", scsi_hba_tran))
@@ -357,6 +384,10 @@
 _NOTE(DATA_READABLE_WITHOUT_LOCK(sata_pmport_info::pmport_sata_drive))
 _NOTE(DATA_READABLE_WITHOUT_LOCK(sata_pmult_info::pmult_dev_port))
 _NOTE(DATA_READABLE_WITHOUT_LOCK(sata_pmult_info::pmult_num_dev_ports))
+#ifdef SATA_DEBUG
+_NOTE(SCHEME_PROTECTS_DATA("No Mutex Needed", mbuf_count))
+_NOTE(SCHEME_PROTECTS_DATA("No Mutex Needed", mbuffail_count))
+#endif
 
 /* End of warlock directives */
 
@@ -3038,6 +3069,13 @@
  * Supported capabilities:
  * auto-rqsense		(always supported)
  * tagged-qing		(supported if HBA supports it)
+ * untagged-qing	(could be supported if disk supports it, but because
+ *			 caching behavior allowing untagged queuing actually
+ *			 results in reduced performance.  sd tries to throttle
+ *			 back to only 3 outstanding commands, which may
+ *			 work for real SCSI disks, but with read ahead
+ *			 caching, having more than 1 outstanding command
+ *			 results in cache thrashing.)
  * dma_max
  * interconnect-type	(INTERCONNECT_SATA)
  *
@@ -3097,16 +3135,31 @@
 		else rval = -1;
 		break;
 
+	/*
+	 * untagged queuing cause a performance inversion because of
+	 * the way sd operates.  Because of this reason we do not
+	 * use it when available.
+	 */
+#if defined(_UNTAGGED_QING_SUPPORTED)
+	case SCSI_CAP_UNTAGGED_QING:
+		if (SATA_QDEPTH(sata_hba_inst) > 1)
+			rval = 1;	/* Untagged queuing supported */
+		else
+			rval = -1;	/* Untagged queuing not supported */
+		break;
+#endif
+
 	case SCSI_CAP_TAGGED_QING:
-		/*
-		 * It is enough if the controller supports queuing, regardless
-		 * of the device. NCQ support is an internal implementation
-		 * feature used between HBA and the device.
-		 */
-		if (SATA_QDEPTH(sata_hba_inst) > 1)
-			rval = 1;	/* Queuing supported */
+		/* This can TCQ or NCQ */
+		if (sata_func_enable & SATA_ENABLE_QUEUING &&
+		    ((sdinfo->satadrv_features_support & SATA_DEV_F_TCQ &&
+		    SATA_FEATURES(sata_hba_inst) & SATA_CTLF_QCMD) ||
+		    (sata_func_enable & SATA_ENABLE_NCQ &&
+		    sdinfo->satadrv_features_support & SATA_DEV_F_NCQ &&
+		    SATA_FEATURES(sata_hba_inst) & SATA_CTLF_NCQ)))
+			rval = 1;	/* Tagged queuing supported */
 		else
-			rval = -1;	/* Queuing not supported */
+			rval = -1;	/* Tagged queuing not supported */
 		break;
 
 	case SCSI_CAP_DMA_MAX:
@@ -3179,8 +3232,11 @@
 	case SCSI_CAP_TAGGED_QING:
 	case SCSI_CAP_DMA_MAX:
 	case SCSI_CAP_INTERCONNECT_TYPE:
+#if defined(_UNTAGGED_QING_SUPPORTED)
+	case SCSI_CAP_UNTAGGED_QING:
 		rval = 0;		/* Capability cannot be changed */
 		break;
+#endif
 
 	default:
 		rval = -1;
@@ -4595,9 +4651,9 @@
 	pc = scsipkt->pkt_cdbp[2] >> 6;
 	page_code = scsipkt->pkt_cdbp[2] & 0x3f;
 
-	/* Reject not supported request for all but cummulative values */
+	/* Reject not supported request for all but cumulative values */
 	switch (pc) {
-	case PC_CUMMULATIVE_VALUES:
+	case PC_CUMULATIVE_VALUES:
 		break;
 	default:
 		*scsipkt->pkt_scbp = STATUS_CHECK;
@@ -4937,7 +4993,7 @@
 			scmd->satacmd_features_reg_ext =
 			    scmd->satacmd_sec_count_msb;
 			scmd->satacmd_sec_count_msb = 0;
-			scmd->satacmd_rle_sata_cmd = NULL;
+			scmd->satacmd_rle_sata_cmd = &sata_rle_cmd;
 		} else if ((sdinfo->satadrv_features_support &
 		    SATA_DEV_F_TCQ) &&
 		    (SATA_FEATURES(spx->txlt_sata_hba_inst) &
@@ -5153,7 +5209,7 @@
 			scmd->satacmd_features_reg_ext =
 			    scmd->satacmd_sec_count_msb;
 			scmd->satacmd_sec_count_msb = 0;
-			scmd->satacmd_rle_sata_cmd = NULL;
+			scmd->satacmd_rle_sata_cmd = &sata_rle_cmd;
 		} else if ((sdinfo->satadrv_features_support &
 		    SATA_DEV_F_TCQ) &&
 		    (SATA_FEATURES(spx->txlt_sata_hba_inst) &
@@ -5693,7 +5749,7 @@
 	}
 	*lba = (*lba << 8) | sata_cmd->satacmd_lba_high_lsb;
 	*lba = (*lba << 8) | sata_cmd->satacmd_lba_mid_lsb;
-	*lba = (*lba << 8) | sata_cmd->satacmd_lba_high_lsb;
+	*lba = (*lba << 8) | sata_cmd->satacmd_lba_low_lsb;
 }
 
 /*
@@ -5803,9 +5859,9 @@
 			} else {
 				sata_extract_error_lba(spx, &lba);
 				sense->es_info_1 = (lba & 0xFF000000) >> 24;
-				sense->es_info_1 = (lba & 0xFF0000) >> 16;
-				sense->es_info_1 = (lba & 0xFF00) >> 8;
-				sense->es_info_1 = lba & 0xFF;
+				sense->es_info_2 = (lba & 0xFF0000) >> 16;
+				sense->es_info_3 = (lba & 0xFF00) >> 8;
+				sense->es_info_4 = lba & 0xFF;
 			}
 		} else {
 			/* Invalid extended sense info */
@@ -8366,7 +8422,7 @@
 		(void) strlcat(msg_buf, ", Native Command Queueing",
 		    MAXPATHLEN);
 	if (sdinfo->satadrv_features_support & SATA_DEV_F_TCQ)
-		(void) strlcat(msg_buf, ", Queuing", MAXPATHLEN);
+		(void) strlcat(msg_buf, ", Legacy Tagged Queuing", MAXPATHLEN);
 	if ((sdinfo->satadrv_id.ai_cmdset82 & SATA_SMART_SUPPORTED) &&
 	    (sdinfo->satadrv_id.ai_features85 & SATA_SMART_ENABLED))
 		(void) strlcat(msg_buf, ", SMART", MAXPATHLEN);
@@ -8383,6 +8439,13 @@
 			sdinfo->satadrv_queue_depth);
 	}
 
+	if (sdinfo->satadrv_features_support &
+		(SATA_DEV_F_TCQ | SATA_DEV_F_NCQ)) {
+		(void) sprintf(msg_buf, "\tqueue depth %d\n",
+				sdinfo->satadrv_queue_depth);
+		cmn_err(CE_CONT, "?%s", msg_buf);
+	}
+
 #ifdef __i386
 	(void) sprintf(msg_buf, "\tcapacity = %llu sectors\n",
 		sdinfo->satadrv_capacity);
@@ -8689,6 +8752,7 @@
 	bp = spx->txlt_sata_pkt->satapkt_cmd.satacmd_bp;
 	ASSERT(bp != NULL);
 
+
 	if (spx->txlt_buf_dma_handle == NULL) {
 		/*
 		 * No DMA resources allocated so far - this is a first call
@@ -9177,15 +9241,15 @@
 				    SATA_DEV_F_SATA1;
 			}
 		}
-
-		sdinfo->satadrv_queue_depth = sdinfo->satadrv_id.ai_qdepth;
-		if (sdinfo->satadrv_id.ai_cmdset83 & SATA_RW_DMA_QUEUED_CMD)
-			++sdinfo->satadrv_queue_depth;
-
 		if ((sdinfo->satadrv_id.ai_cmdset83 & SATA_RW_DMA_QUEUED_CMD) &&
 		    (sdinfo->satadrv_id.ai_features86 & SATA_RW_DMA_QUEUED_CMD))
 			sdinfo->satadrv_features_support |= SATA_DEV_F_TCQ;
 
+		sdinfo->satadrv_queue_depth = sdinfo->satadrv_id.ai_qdepth;
+		if ((sdinfo->satadrv_features_support & SATA_DEV_F_NCQ) ||
+			(sdinfo->satadrv_features_support & SATA_DEV_F_TCQ))
+			++sdinfo->satadrv_queue_depth;
+
 		rval = 0;
 	}
 fail:
@@ -11039,7 +11103,7 @@
 
 
 /*
- * sata_set_drive_featues function compares current device features setting
+ * sata_set_drive_features function compares current device features setting
  * with the saved device features settings and, if there is a difference,
  * it restores device features setting to the previously saved state.
  * Device Identify data has to be current.
@@ -11051,7 +11115,7 @@
  * to be updated after features are set.
  *
  * Returns TRUE if successful or there was nothing to do.
- * Returns FALSE if device features cound not be set .
+ * Returns FALSE if device features could not be set .
  *
  * Note: This function may fail the port, making it inaccessible.
  * Explicit port disconnect/connect or physical device
@@ -11165,7 +11229,7 @@
 
 /*
  *
- * Returns 1 if threshold exceeded, 0 if threshold no exceeded, -1 if
+ * Returns 1 if threshold exceeded, 0 if threshold not exceeded, -1 if
  * unable to determine.
  *
  * Cannot be called in an interrupt context.
@@ -11518,7 +11582,7 @@
 	scmd->satacmd_flags.sata_data_direction = SATA_DIR_READ;
 
 	/*
-	 * Allocate buffer for Identify Data return data
+	 * Allocate buffer for SMART SELFTEST LOG
 	 */
 	scmd->satacmd_bp = sata_alloc_local_buffer(spx,
 	    sizeof (struct smart_selftest_log));
@@ -11531,7 +11595,7 @@
 		return (-1);
 	}
 
-	/* Build SMART_READ_DATA cmd in the sata_pkt */
+	/* Build SMART_READ_LOG cmd in the sata_pkt */
 	scmd->satacmd_addr_type = 0;		/* N/A */
 	scmd->satacmd_sec_count_lsb = 1;	/* One sector of SMART log */
 	scmd->satacmd_lba_low_lsb = SMART_SELFTEST_LOG_PAGE;
@@ -11629,7 +11693,7 @@
 		return (-1);
 	}
 
-	/* Build SMART_READ_DATA cmd in the sata_pkt */
+	/* Build SMART_READ_LOG cmd in the sata_pkt */
 	scmd->satacmd_addr_type = 0;		/* N/A */
 	scmd->satacmd_sec_count_lsb = log_size;	/* what the caller asked for */
 	scmd->satacmd_lba_low_lsb = which_log;	/* which log page */
@@ -11717,7 +11781,7 @@
 	scmd->satacmd_flags.sata_data_direction = SATA_DIR_READ;
 
 	/*
-	 * Allocate buffer for SMART extended self-test log
+	 * Allocate buffer for SMART READ LOG EXTENDED command
 	 */
 	scmd->satacmd_bp = sata_alloc_local_buffer(spx,
 	    sizeof (struct read_log_ext_directory));
@@ -11730,7 +11794,7 @@
 		return (-1);
 	}
 
-	/* Build READ LOG EXT w/ extended self-test log cmd in the sata_pkt */
+	/* Build READ LOG EXT w/ log directory cmd in the  sata_pkt */
 	scmd->satacmd_addr_type = ATA_ADDR_LBA48;
 	scmd->satacmd_sec_count_lsb = 1;	/* One sector of directory */
 	scmd->satacmd_sec_count_msb = 0;	/* One sector of directory */
--- a/usr/src/uts/common/sys/sata/sata_defs.h	Tue Aug 15 14:28:22 2006 -0700
+++ b/usr/src/uts/common/sys/sata/sata_defs.h	Tue Aug 15 15:13:46 2006 -0700
@@ -131,6 +131,7 @@
 /* Generic ATA definitions */
 
 #define	SATA_TAG_QUEUING_SHIFT 3
+#define	SATA_TAG_QUEUING_MASK 0x1f
 /*
  * Identify Device data
  * Although bot ATA and ATAPI devices' Identify Data has the same lenght,
@@ -424,8 +425,33 @@
 #define	SCSI_INFO_EXCEPTIONS_PARAM_LEN	4
 
 #define	READ_LOG_EXT_LOG_DIRECTORY	0
+#define	READ_LOG_EXT_NCQ_ERROR_RECOVERY	0x10
 #define	SMART_SELFTEST_LOG_PAGE		6
 #define	EXT_SMART_SELFTEST_LOG_PAGE	7
+
+/*
+ * SATA NCQ error recovery page (0x10)
+ */
+struct sata_ncq_error_recovery_page {
+	uint8_t	ncq_tag;
+	uint8_t reserved1;
+	uint8_t ncq_status;
+	uint8_t ncq_error;
+	uint8_t ncq_sector_number;
+	uint8_t ncq_cyl_low;
+	uint8_t ncq_cyl_high;
+	uint8_t ncq_dev_head;
+	uint8_t ncq_sector_number_ext;
+	uint8_t ncq_cyl_low_ext;
+	uint8_t ncq_cyl_high_ext;
+	uint8_t reserved2;
+	uint8_t ncq_sector_count;
+	uint8_t ncq_sector_count_ext;
+	uint8_t reserved3[242];
+	uint8_t ncq_vendor_unique[255];
+	uint8_t ncq_checksum;
+};
+
 /*
  * SMART data structures
  */
@@ -496,7 +522,7 @@
  * These eventually need to go to a generic scsi hearder file
  * for now they will reside here
  */
-#define	PC_CUMMULATIVE_VALUES			0x01
+#define	PC_CUMULATIVE_VALUES			0x01
 #define	PAGE_CODE_GET_SUPPORTED_LOG_PAGES	0x00
 #define	PAGE_CODE_SELF_TEST_RESULTS		0x10
 #define	PAGE_CODE_INFORMATION_EXCEPTIONS	0x2f
--- a/usr/src/uts/common/sys/sata/sata_hba.h	Tue Aug 15 14:28:22 2006 -0700
+++ b/usr/src/uts/common/sys/sata/sata_hba.h	Tue Aug 15 15:13:46 2006 -0700
@@ -347,7 +347,7 @@
 						 * Ptr to FPDMA error
 						 * retrieval cmd
 						 */
-	struct sata_cmd	*satacmd_rle_sata_cmd;
+	const struct sata_cmd	*satacmd_rle_sata_cmd;
 
 	int		satacmd_num_dma_cookies; /* number of dma cookies */
 						/* ptr to dma cookie list */
@@ -379,13 +379,16 @@
 #define	SATA_DIR_WRITE		0x0004	/* Writing data to a device */
 
 /*
- * Tagged Queuing type flags (satacmd_flags).
+ * Tagged Queuing type flags
+ * 	satacmd_flags.sata_queue_stag
+ * 	satacmd_flags.sata_queue_otag
+ *
  * These flags indicate how the SATA command should be queued.
  *
- * SATA_QUEUE_STAG_CMD
+ * sata_queue_stag
  * Simple-queue-tagged command. It may be executed out-of-order in respect
  * to other queued commands.
- * SATA_QUEUE_OTAG_CMD
+ * sata_queue_otag
  * Ordered-queue-tagged command. It cannot be executed out-of-order in
  * respect to other commands, i.e. it should be executed in the order of
  * being transported to the HBA.
@@ -394,12 +397,10 @@
  * to be put at the head of the queue are treated as SATA_QUEUE_OTAG_CMD
  * tagged commands.
  */
-#define	SATA_QUEUE_STAG_CMD	0x0010	/* simple-queue-tagged command */
-#define	SATA_QUEUE_OTAG_CMD	0x0020	/* ordered-queue-tagged command */
 
 
 /*
- * Queuing command set-up flag (satacmd_flags).
+ * Queuing command set-up flag (satacmd_flags.sata_queued).
  * This flag indicates that sata_cmd was set-up for DMA Queued command
  * (either READ_DMA_QUEUED, READ_DMA_QUEUED_EXT, WRITE_DMA_QUEUED or
  * WRITE_DMA_QUEUED_EXT command) or one of the Native Command Queuing commands
@@ -409,19 +410,18 @@
  * either legacy queuing (indicated by Device Identify data word 83 bit 2)
  * or NCQ (indicated by  word 76 of Device Identify data).
  */
-#define	SATA_QUEUED_CMD			0x0100
-
 
 /*
- * Reset state handling (satacmd_flags).
+ * Reset state handling
+ *	satacmd_flags.sata_ignore_dev_reset
+ *	satacmd_flags.sata_clear_dev_reset
+ *
  * SATA HBA device enters reset state if the device was subjected to
  * the Device Reset (may also enter this state if the device was reset
  * as a side effect of port reset). SATA HBA driver sets this state.
  * Device stays in this condition until explicit request from SATA HBA
- * framework (SATA_CLEAR_DEV_RESET_STATE flag) to clear the state.
+ * framework to clear the state.
  */
-#define	SATA_IGNORE_DEV_RESET_STATE	0x1000
-#define	SATA_CLEAR_DEV_RESET_STATE	0x2000
 
 /*
  * SATA Packet structure (rev 1)