Mercurial > illumos > illumos-gate
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)