changeset 1940:c302ad4d1aa7

6404894 Informational exceptions log parameter should be 4 bytes 6412375 Need to add support for tagged queuing in the marvell88sx driver 6412380 sata framework doesn't always utilize correct queuing mode 6412384 queue depth is incorrect for SATA controllers 6412386 Some SATA disks do no use the 19th entry in the self test log 6412390 SATA LOG SENSE results can be incorrect 6412398 allow scatter/gather list length for marvell88sx to be tunable 6420987 sata_hba_ioctl() may hold mutex upon exit
author ls24207
date Fri, 05 May 2006 13:30:06 -0700
parents 41d0b91fb239
children 1843b345392c
files usr/src/uts/common/io/sata/impl/sata.c usr/src/uts/common/sys/sata/impl/sata.h usr/src/uts/common/sys/sata/sata_defs.h
diffstat 3 files changed, 226 insertions(+), 90 deletions(-) [+]
line wrap: on
line diff
--- a/usr/src/uts/common/io/sata/impl/sata.c	Fri May 05 13:27:41 2006 -0700
+++ b/usr/src/uts/common/io/sata/impl/sata.c	Fri May 05 13:30:06 2006 -0700
@@ -63,7 +63,7 @@
 #define	SATA_ENABLE_QUEUING		1
 #define	SATA_ENABLE_NCQ			2
 #define	SATA_ENABLE_PROCESS_EVENTS	4
-static 	int sata_func_enable = SATA_ENABLE_PROCESS_EVENTS;
+int sata_func_enable = SATA_ENABLE_PROCESS_EVENTS | SATA_ENABLE_QUEUING;
 
 #ifdef SATA_DEBUG
 #define	SATA_LOG_D(args)	sata_log args
@@ -1106,6 +1106,8 @@
 		}
 		/* Sanity check */
 		if (SATA_PORT_DEACTIVATE_FUNC(sata_hba_inst) == NULL) {
+			mutex_exit(&SATA_CPORT_INFO(sata_hba_inst, cport)->
+			    cport_mutex);
 			/* No physical port deactivation supported. */
 			break;
 		}
@@ -2714,6 +2716,7 @@
  * SCMD_WRITE_G4
  * SCMD_WRITE_G5
  * SCMD_SEEK		(noop)
+ * SCMD_SDIAG
  *
  * All other commands are rejected as unsupported.
  *
@@ -2860,7 +2863,6 @@
 		rval = sata_txlt_nodata_cmd_immediate(spx);
 		break;
 
-
 		/* Other cases will be filed later */
 		/* postponed until phase 2 of the development */
 	default:
@@ -4879,34 +4881,49 @@
 	 * to appropriate command if possible
 	 */
 	if (sata_func_enable & SATA_ENABLE_QUEUING) {
-		if (sdinfo->satadrv_queue_depth > 1 &&
-		    SATA_QDEPTH(spx->txlt_sata_hba_inst) > 1) {
-			/* Queuing supported by controller and device */
-			if ((sata_func_enable & SATA_ENABLE_NCQ) &&
-			    (sdinfo->satadrv_features_support &
-			    SATA_DEV_F_NCQ) &&
-			    (SATA_FEATURES(spx->txlt_sata_hba_inst) &
-			    SATA_CTLF_NCQ)) {
-				/* NCQ supported - use FPDMA READ */
+		boolean_t using_queuing;
+
+		/* Queuing supported by controller and device? */
+		if ((sata_func_enable & SATA_ENABLE_NCQ) &&
+		    (sdinfo->satadrv_features_support &
+		    SATA_DEV_F_NCQ) &&
+		    (SATA_FEATURES(spx->txlt_sata_hba_inst) &
+		    SATA_CTLF_NCQ)) {
+			using_queuing = B_TRUE;
+
+			/* NCQ supported - use FPDMA READ */
+			scmd->satacmd_cmd_reg =
+			    SATAC_READ_FPDMA_QUEUED;
+			scmd->satacmd_features_reg_ext =
+			    scmd->satacmd_sec_count_msb;
+			scmd->satacmd_sec_count_msb = 0;
+			scmd->satacmd_rle_sata_cmd = NULL;
+		} else if ((sdinfo->satadrv_features_support &
+		    SATA_DEV_F_TCQ) &&
+		    (SATA_FEATURES(spx->txlt_sata_hba_inst) &
+		    SATA_CTLF_QCMD)) {
+			using_queuing = B_TRUE;
+
+			/* Legacy queueing */
+			if (sdinfo->satadrv_features_support &
+			    SATA_DEV_F_LBA48) {
 				scmd->satacmd_cmd_reg =
-				    SATAC_READ_FPDMA_QUEUED;
+				    SATAC_READ_DMA_QUEUED_EXT;
 				scmd->satacmd_features_reg_ext =
 				    scmd->satacmd_sec_count_msb;
 				scmd->satacmd_sec_count_msb = 0;
 			} else {
-				/* Legacy queueing */
-				if (sdinfo->satadrv_features_support &
-				    SATA_DEV_F_LBA48) {
-					scmd->satacmd_cmd_reg =
-					    SATAC_READ_DMA_QUEUED_EXT;
-					scmd->satacmd_features_reg_ext =
-					    scmd->satacmd_sec_count_msb;
-					scmd->satacmd_sec_count_msb = 0;
-				} else {
-					scmd->satacmd_cmd_reg =
-					    SATAC_READ_DMA_QUEUED;
-				}
-			}
+				scmd->satacmd_cmd_reg =
+				    SATAC_READ_DMA_QUEUED;
+			}
+		} else	/* Queuing not supported */
+			using_queuing = B_FALSE;
+
+		/*
+		 * If queuing, the sector count goes in the features register
+		 * and the secount count will contain the tag.
+		 */
+		if (using_queuing) {
 			scmd->satacmd_features_reg =
 			    scmd->satacmd_sec_count_lsb;
 			scmd->satacmd_sec_count_lsb = 0;
@@ -5080,35 +5097,45 @@
 	 * to appropriate command if possible
 	 */
 	if (sata_func_enable & SATA_ENABLE_QUEUING) {
-		if (sdinfo->satadrv_queue_depth > 1 &&
-		    SATA_QDEPTH(spx->txlt_sata_hba_inst) > 1) {
-			/* Queuing supported by controller and device */
-			if ((sata_func_enable & SATA_ENABLE_NCQ) &&
-			    (sdinfo->satadrv_features_support &
-			    SATA_DEV_F_NCQ) &&
-			    (SATA_FEATURES(spx->txlt_sata_hba_inst) &
-			    SATA_CTLF_NCQ)) {
-				/* NCQ supported - use FPDMA WRITE */
+		boolean_t using_queuing;
+
+		/* Queuing supported by controller and device? */
+		if ((sata_func_enable & SATA_ENABLE_NCQ) &&
+		    (sdinfo->satadrv_features_support &
+		    SATA_DEV_F_NCQ) &&
+		    (SATA_FEATURES(spx->txlt_sata_hba_inst) &
+		    SATA_CTLF_NCQ)) {
+			using_queuing = B_TRUE;
+
+			/* NCQ supported - use FPDMA WRITE */
+			scmd->satacmd_cmd_reg =
+			    SATAC_WRITE_FPDMA_QUEUED;
+			scmd->satacmd_features_reg_ext =
+			    scmd->satacmd_sec_count_msb;
+			scmd->satacmd_sec_count_msb = 0;
+			scmd->satacmd_rle_sata_cmd = NULL;
+		} else if ((sdinfo->satadrv_features_support &
+		    SATA_DEV_F_TCQ) &&
+		    (SATA_FEATURES(spx->txlt_sata_hba_inst) &
+		    SATA_CTLF_QCMD)) {
+			using_queuing = B_TRUE;
+
+			/* Legacy queueing */
+			if (sdinfo->satadrv_features_support &
+			    SATA_DEV_F_LBA48) {
 				scmd->satacmd_cmd_reg =
-				    SATAC_WRITE_FPDMA_QUEUED;
+				    SATAC_WRITE_DMA_QUEUED_EXT;
 				scmd->satacmd_features_reg_ext =
 				    scmd->satacmd_sec_count_msb;
 				scmd->satacmd_sec_count_msb = 0;
-				scmd->satacmd_rle_sata_cmd = NULL;
 			} else {
-				/* Legacy queueing */
-				if (sdinfo->satadrv_features_support &
-				    SATA_DEV_F_LBA48) {
-					scmd->satacmd_cmd_reg =
-					    SATAC_WRITE_DMA_QUEUED_EXT;
-					scmd->satacmd_features_reg_ext =
-					    scmd->satacmd_sec_count_msb;
-					scmd->satacmd_sec_count_msb = 0;
-				} else {
-					scmd->satacmd_cmd_reg =
-					    SATAC_WRITE_DMA_QUEUED;
-				}
-			}
+				scmd->satacmd_cmd_reg =
+				    SATAC_WRITE_DMA_QUEUED;
+			}
+		} else	/* Queuing not supported */
+			using_queuing = B_FALSE;
+
+		if (using_queuing) {
 			scmd->satacmd_features_reg =
 			    scmd->satacmd_sec_count_lsb;
 			scmd->satacmd_sec_count_lsb = 0;
@@ -5320,7 +5347,6 @@
 	return (TRAN_ACCEPT);
 }
 
-
 /*
  * Send pkt to SATA HBA driver
  *
@@ -6414,10 +6440,13 @@
 		rval = sata_ext_smart_selftest_read_log(sata_hba_inst, sdinfo,
 		    ext_selftest_log, 0);
 		if (rval == 0) {
-			int index;
+			int index, start_index;
 			struct smart_ext_selftest_log_entry *entry;
+			static const struct smart_ext_selftest_log_entry empty =
+			    {0};
 			uint16_t block_num;
 			int count;
+			boolean_t only_one_block = B_FALSE;
 
 			index = ext_selftest_log->
 			    smart_ext_selftest_log_index[0];
@@ -6427,6 +6456,7 @@
 				goto out;
 
 			--index;	/* Correct for 0 origin */
+			start_index = index;	/* remember where we started */
 			block_num = index / ENTRIES_PER_EXT_SELFTEST_LOG_BLK;
 			if (block_num != 0) {
 				rval = sata_ext_smart_selftest_read_log(
@@ -6449,9 +6479,28 @@
 				uint8_t add_sense_code;
 				uint8_t add_sense_code_qual;
 
+				/* If this is an unused entry, we are done */
+				if (bcmp(entry, &empty, sizeof (empty)) == 0) {
+					/* Broken firmware on some disks */
+					if (index + 1 ==
+					    ENTRIES_PER_EXT_SELFTEST_LOG_BLK) {
+						--entry;
+						--index;
+						if (bcmp(entry, &empty,
+						    sizeof (empty)) == 0)
+							goto out;
+					} else
+						goto out;
+				}
+
+				if (only_one_block &&
+				    start_index == index)
+					goto out;
+
 				lpp->param_code[0] = 0;
 				lpp->param_code[1] = count;
-				lpp->param_ctrl_flags = 0;
+				lpp->param_ctrl_flags =
+				    LOG_CTRL_LP | LOG_CTRL_LBIN;
 				lpp->param_len =
 				    SCSI_LOG_SENSE_SELFTEST_PARAM_LEN;
 
@@ -6521,20 +6570,38 @@
 				    smart_ext_selftest_log_timestamp[1];
 				lpp->param_values[3] = entry->
 				    smart_ext_selftest_log_timestamp[0];
-				lpp->param_values[4] = 0;
-				lpp->param_values[5] = 0;
-				lpp->param_values[6] = entry->
-				    smart_ext_selftest_log_failing_lba[5];
-				lpp->param_values[7] = entry->
-				    smart_ext_selftest_log_failing_lba[4];
-				lpp->param_values[8] = entry->
-				    smart_ext_selftest_log_failing_lba[3];
-				lpp->param_values[9] = entry->
-				    smart_ext_selftest_log_failing_lba[2];
-				lpp->param_values[10] = entry->
-				    smart_ext_selftest_log_failing_lba[1];
-				lpp->param_values[11] = entry->
-				    smart_ext_selftest_log_failing_lba[0];
+				if (status != 0) {
+					lpp->param_values[4] = 0;
+					lpp->param_values[5] = 0;
+					lpp->param_values[6] = entry->
+					    smart_ext_selftest_log_failing_lba
+					    [5];
+					lpp->param_values[7] = entry->
+					    smart_ext_selftest_log_failing_lba
+					    [4];
+					lpp->param_values[8] = entry->
+					    smart_ext_selftest_log_failing_lba
+					    [3];
+					lpp->param_values[9] = entry->
+					    smart_ext_selftest_log_failing_lba
+					    [2];
+					lpp->param_values[10] = entry->
+					    smart_ext_selftest_log_failing_lba
+					    [1];
+					lpp->param_values[11] = entry->
+					    smart_ext_selftest_log_failing_lba
+					    [0];
+				} else {	/* No bad block address */
+					lpp->param_values[4] = 0xff;
+					lpp->param_values[5] = 0xff;
+					lpp->param_values[6] = 0xff;
+					lpp->param_values[7] = 0xff;
+					lpp->param_values[8] = 0xff;
+					lpp->param_values[9] = 0xff;
+					lpp->param_values[10] = 0xff;
+					lpp->param_values[11] = 0xff;
+				}
+
 				lpp->param_values[12] = sense_key;
 				lpp->param_values[13] = add_sense_code;
 				lpp->param_values[14] = add_sense_code_qual;
@@ -6565,14 +6632,16 @@
 						    [1] == 0))
 							goto out;
 						block_num =
-						    logdir.read_log_ext_nblks[0]
+						    logdir.read_log_ext_nblks
 						    [EXT_SMART_SELFTEST_LOG_PAGE
-						    - 1];
+						    - 1][0];
 						block_num |= logdir.
-						    read_log_ext_nblks[1]
+						    read_log_ext_nblks
 						    [EXT_SMART_SELFTEST_LOG_PAGE
-						    - 1] << 8;
+						    - 1][1] << 8;
 						--block_num;
+						only_one_block =
+						    (block_num == 0);
 					}
 					rval = sata_ext_smart_selftest_read_log(
 					    sata_hba_inst, sdinfo,
@@ -6605,6 +6674,8 @@
 			int index;
 			int count;
 			struct smart_selftest_log_entry *entry;
+			static const struct smart_selftest_log_entry empty =
+			    { 0 };
 
 			index = selftest_log->smart_selftest_log_index;
 			if (index == 0)
@@ -6621,9 +6692,13 @@
 				uint8_t add_sense_code;
 				uint8_t add_sense_code_qual;
 
+				if (bcmp(entry, &empty, sizeof (empty)) == 0)
+					goto done;
+
 				lpp->param_code[0] = 0;
 				lpp->param_code[1] = count;
-				lpp->param_ctrl_flags = 0;
+				lpp->param_ctrl_flags =
+				    LOG_CTRL_LP | LOG_CTRL_LBIN;
 				lpp->param_len =
 				    SCSI_LOG_SENSE_SELFTEST_PARAM_LEN;
 
@@ -6692,18 +6767,29 @@
 				    smart_selftest_log_timestamp[1];
 				lpp->param_values[3] = entry->
 				    smart_selftest_log_timestamp[0];
-				lpp->param_values[4] = 0;
-				lpp->param_values[5] = 0;
-				lpp->param_values[6] = 0;
-				lpp->param_values[7] = 0;
-				lpp->param_values[8] = entry->
-				    smart_selftest_log_failing_lba[3];
-				lpp->param_values[9] = entry->
-				    smart_selftest_log_failing_lba[2];
-				lpp->param_values[10] = entry->
-				    smart_selftest_log_failing_lba[1];
-				lpp->param_values[11] = entry->
-				    smart_selftest_log_failing_lba[0];
+				if (status != 0) {
+					lpp->param_values[4] = 0;
+					lpp->param_values[5] = 0;
+					lpp->param_values[6] = 0;
+					lpp->param_values[7] = 0;
+					lpp->param_values[8] = entry->
+					    smart_selftest_log_failing_lba[3];
+					lpp->param_values[9] = entry->
+					    smart_selftest_log_failing_lba[2];
+					lpp->param_values[10] = entry->
+					    smart_selftest_log_failing_lba[1];
+					lpp->param_values[11] = entry->
+					    smart_selftest_log_failing_lba[0];
+				} else {	/* No block address */
+					lpp->param_values[4] = 0xff;
+					lpp->param_values[5] = 0xff;
+					lpp->param_values[6] = 0xff;
+					lpp->param_values[7] = 0xff;
+					lpp->param_values[8] = 0xff;
+					lpp->param_values[9] = 0xff;
+					lpp->param_values[10] = 0xff;
+					lpp->param_values[11] = 0xff;
+				}
 				lpp->param_values[12] = sense_key;
 				lpp->param_values[13] = add_sense_code;
 				lpp->param_values[14] = add_sense_code_qual;
@@ -6765,7 +6851,7 @@
 		break;
 	case 0:
 	case -1:	/* failed to get data */
-		lpp->param_values[0] = 0;
+		lpp->param_values[0] = 0;	/* No failure predicted */
 		lpp->param_values[1] = 0;
 		break;
 #if defined(SATA_DEBUG)
@@ -6797,7 +6883,8 @@
 		kmem_free(smart_data, 512);
 	}
 
-	lpp->param_values[2] = temp;
+	lpp->param_values[2] = temp;	/* most recent temperature */
+	lpp->param_values[3] = 0;	/* required vendor specific byte */
 
 	lpp->param_len = SCSI_INFO_EXCEPTIONS_PARAM_LEN;
 
@@ -8225,7 +8312,7 @@
 	if (sdinfo->satadrv_features_support & SATA_DEV_F_NCQ)
 		(void) strlcat(msg_buf, ", Native Command Queueing",
 		    MAXPATHLEN);
-	else if (sdinfo->satadrv_id.ai_cmdset83 & SATA_RW_DMA_QUEUED_CMD)
+	if (sdinfo->satadrv_features_support & SATA_DEV_F_TCQ)
 		(void) strlcat(msg_buf, ", Queuing", MAXPATHLEN);
 	if ((sdinfo->satadrv_id.ai_cmdset82 & SATA_SMART_SUPPORTED) &&
 	    (sdinfo->satadrv_id.ai_features85 & SATA_SMART_ENABLED))
@@ -8923,8 +9010,11 @@
 
 		sdinfo->satadrv_queue_depth = sdinfo->satadrv_id.ai_qdepth;
 		if (sdinfo->satadrv_id.ai_cmdset83 & SATA_RW_DMA_QUEUED_CMD)
-			if (sdinfo->satadrv_queue_depth == 0)
-				sdinfo->satadrv_queue_depth = 1;
+			++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;
 
 		rval = 0;
 	}
@@ -10959,16 +11049,23 @@
 	scmd->satacmd_features_reg = SATA_SMART_RETURN_STATUS;
 	scmd->satacmd_device_reg = 0;		/* Always device 0 */
 	scmd->satacmd_cmd_reg = SATAC_SMART;
+	mutex_exit(&(SATA_CPORT_MUTEX(sata_hba_inst,
+	    sdinfo->satadrv_addr.cport)));
+
 
 	/* Send pkt to SATA HBA driver */
 	if ((*SATA_START_FUNC(sata_hba_inst))(SATA_DIP(sata_hba_inst), spkt) !=
 	    SATA_TRAN_ACCEPTED ||
 	    spkt->satapkt_reason != SATA_PKT_COMPLETED) {
+		mutex_enter(&(SATA_CPORT_MUTEX(sata_hba_inst,
+		    sdinfo->satadrv_addr.cport)));
 		/*
 		 * Whoops, no SMART RETURN STATUS
 		 */
 		rval = -1;
 	} else {
+		mutex_enter(&(SATA_CPORT_MUTEX(sata_hba_inst,
+		    sdinfo->satadrv_addr.cport)));
 		if (scmd->satacmd_error_reg & SATA_ERROR_ABORT) {
 			rval = -1;
 			goto fail;
@@ -11065,17 +11162,23 @@
 	scmd->satacmd_features_reg = SATA_SMART_READ_DATA;
 	scmd->satacmd_device_reg = 0;		/* Always device 0 */
 	scmd->satacmd_cmd_reg = SATAC_SMART;
+	mutex_exit(&(SATA_CPORT_MUTEX(sata_hba_inst,
+	    sdinfo->satadrv_addr.cport)));
 
 	/* Send pkt to SATA HBA driver */
 	if ((*SATA_START_FUNC(sata_hba_inst))(SATA_DIP(sata_hba_inst), spkt) !=
 	    SATA_TRAN_ACCEPTED ||
 	    spkt->satapkt_reason != SATA_PKT_COMPLETED) {
+		mutex_enter(&(SATA_CPORT_MUTEX(sata_hba_inst,
+		    sdinfo->satadrv_addr.cport)));
 		/*
 		 * Whoops, no SMART DATA available
 		 */
 		rval = -1;
 		goto fail;
 	} else {
+		mutex_enter(&(SATA_CPORT_MUTEX(sata_hba_inst,
+		    sdinfo->satadrv_addr.cport)));
 		rval = ddi_dma_sync(spx->txlt_buf_dma_handle, 0, 0,
 			DDI_DMA_SYNC_FORKERNEL);
 		if (rval != DDI_SUCCESS) {
@@ -11169,16 +11272,25 @@
 	scmd->satacmd_device_reg = 0;		/* Always device 0 */
 	scmd->satacmd_cmd_reg = SATAC_READ_LOG_EXT;
 
+	mutex_exit(&(SATA_CPORT_MUTEX(sata_hba_inst,
+	    sdinfo->satadrv_addr.cport)));
+
 	/* Send pkt to SATA HBA driver */
 	if ((*SATA_START_FUNC(sata_hba_inst))(SATA_DIP(sata_hba_inst), spkt) !=
 	    SATA_TRAN_ACCEPTED ||
 	    spkt->satapkt_reason != SATA_PKT_COMPLETED) {
+		mutex_enter(&(SATA_CPORT_MUTEX(sata_hba_inst,
+		    sdinfo->satadrv_addr.cport)));
+
 		/*
 		 * Whoops, no SMART selftest log info available
 		 */
 		rval = -1;
 		goto fail;
 	} else {
+		mutex_enter(&(SATA_CPORT_MUTEX(sata_hba_inst,
+		    sdinfo->satadrv_addr.cport)));
+
 		rval = ddi_dma_sync(spx->txlt_buf_dma_handle, 0, 0,
 			DDI_DMA_SYNC_FORKERNEL);
 		if (rval != DDI_SUCCESS) {
@@ -11270,17 +11382,23 @@
 	scmd->satacmd_features_reg = SATA_SMART_READ_LOG;
 	scmd->satacmd_device_reg = 0;		/* Always device 0 */
 	scmd->satacmd_cmd_reg = SATAC_SMART;
+	mutex_exit(&(SATA_CPORT_MUTEX(sata_hba_inst,
+	    sdinfo->satadrv_addr.cport)));
 
 	/* Send pkt to SATA HBA driver */
 	if ((*SATA_START_FUNC(sata_hba_inst))(SATA_DIP(sata_hba_inst), spkt) !=
 	    SATA_TRAN_ACCEPTED ||
 	    spkt->satapkt_reason != SATA_PKT_COMPLETED) {
+		mutex_enter(&(SATA_CPORT_MUTEX(sata_hba_inst,
+		    sdinfo->satadrv_addr.cport)));
 		/*
 		 * Whoops, no SMART DATA available
 		 */
 		rval = -1;
 		goto fail;
 	} else {
+		mutex_enter(&(SATA_CPORT_MUTEX(sata_hba_inst,
+		    sdinfo->satadrv_addr.cport)));
 		rval = ddi_dma_sync(spx->txlt_buf_dma_handle, 0, 0,
 			DDI_DMA_SYNC_FORKERNEL);
 		if (rval != DDI_SUCCESS) {
@@ -11369,16 +11487,25 @@
 	scmd->satacmd_device_reg = 0;		/* Always device 0 */
 	scmd->satacmd_cmd_reg = SATAC_SMART;
 
+	mutex_exit(&(SATA_CPORT_MUTEX(sata_hba_inst,
+	    sdinfo->satadrv_addr.cport)));
+
 	/* Send pkt to SATA HBA driver */
 	if ((*SATA_START_FUNC(sata_hba_inst))(SATA_DIP(sata_hba_inst), spkt) !=
 	    SATA_TRAN_ACCEPTED ||
 	    spkt->satapkt_reason != SATA_PKT_COMPLETED) {
+		mutex_enter(&(SATA_CPORT_MUTEX(sata_hba_inst,
+		    sdinfo->satadrv_addr.cport)));
+
 		/*
 		 * Whoops, no SMART DATA available
 		 */
 		rval = -1;
 		goto fail;
 	} else {
+		mutex_enter(&(SATA_CPORT_MUTEX(sata_hba_inst,
+		    sdinfo->satadrv_addr.cport)));
+
 		rval = ddi_dma_sync(spx->txlt_buf_dma_handle, 0, 0,
 			DDI_DMA_SYNC_FORKERNEL);
 		if (rval != DDI_SUCCESS) {
@@ -11467,16 +11594,23 @@
 	scmd->satacmd_device_reg = 0;		/* Always device 0 */
 	scmd->satacmd_cmd_reg = SATAC_READ_LOG_EXT;
 
+	mutex_exit(&(SATA_CPORT_MUTEX(sata_hba_inst,
+	    sdinfo->satadrv_addr.cport)));
+
 	/* Send pkt to SATA HBA driver */
 	if ((*SATA_START_FUNC(sata_hba_inst))(SATA_DIP(sata_hba_inst), spkt) !=
 	    SATA_TRAN_ACCEPTED ||
 	    spkt->satapkt_reason != SATA_PKT_COMPLETED) {
+		mutex_enter(&(SATA_CPORT_MUTEX(sata_hba_inst,
+		    sdinfo->satadrv_addr.cport)));
 		/*
 		 * Whoops, no SMART selftest log info available
 		 */
 		rval = -1;
 		goto fail;
 	} else {
+		mutex_enter(&(SATA_CPORT_MUTEX(sata_hba_inst,
+		    sdinfo->satadrv_addr.cport)));
 		rval = ddi_dma_sync(spx->txlt_buf_dma_handle, 0, 0,
 			DDI_DMA_SYNC_FORKERNEL);
 		if (rval != DDI_SUCCESS) {
--- a/usr/src/uts/common/sys/sata/impl/sata.h	Fri May 05 13:27:41 2006 -0700
+++ b/usr/src/uts/common/sys/sata/impl/sata.h	Fri May 05 13:30:06 2006 -0700
@@ -320,6 +320,7 @@
 #define	SATA_DEV_F_NCQ			0x08
 #define	SATA_DEV_F_SATA1		0x10
 #define	SATA_DEV_F_SATA2		0x20
+#define	SATA_DEV_F_TCQ			0x40	/* Non NCQ tagged queuing */
 
 /*
  * Drive settings flags (satdrv_settings)
--- a/usr/src/uts/common/sys/sata/sata_defs.h	Fri May 05 13:27:41 2006 -0700
+++ b/usr/src/uts/common/sys/sata/sata_defs.h	Fri May 05 13:30:06 2006 -0700
@@ -130,6 +130,7 @@
 
 /* Generic ATA definitions */
 
+#define	SATA_TAG_QUEUING_SHIFT 3
 /*
  * Identify Device data
  * Although bot ATA and ATAPI devices' Identify Data has the same lenght,
@@ -420,7 +421,7 @@
 #define	SCSI_PREDICTED_FAILURE	0x5d
 #define	SCSI_GENERAL_HD_FAILURE	0x10
 
-#define	SCSI_INFO_EXCEPTIONS_PARAM_LEN	3
+#define	SCSI_INFO_EXCEPTIONS_PARAM_LEN	4
 
 #define	READ_LOG_EXT_LOG_DIRECTORY	0
 #define	SMART_SELFTEST_LOG_PAGE		6
@@ -487,7 +488,7 @@
 
 struct read_log_ext_directory {
 	uint8_t	read_log_ext_vers[2];	/* general purpose log version */
-	uint8_t read_log_ext_nblks[2][255]; /* # of blks @ log addr index+1 */
+	uint8_t read_log_ext_nblks[255][2]; /* # of blks @ log addr index+1 */
 };
 
 /*