Mercurial > illumos > illumos-gate
changeset 10740:b13b4915cb81
PSARC/2009/461 Transport Layer Retries (TLR) Support
6647764 Solaris storage driver Transport Layer Retries (TLR) support
author | jianfei wang - Sun Microsystems - Beijing China <Jianfei.Wang@Sun.COM> |
---|---|
date | Thu, 08 Oct 2009 10:37:32 +0800 |
parents | 01d875748398 |
children | 26a74e07a95b |
files | usr/src/uts/common/io/scsi/adapters/mpt_sas/mptsas.c usr/src/uts/common/io/scsi/adapters/mpt_sas/mptsas_init.c usr/src/uts/common/io/scsi/targets/st.c usr/src/uts/common/sys/scsi/adapters/mpt_sas/mptsas_var.h usr/src/uts/common/sys/scsi/impl/services.h usr/src/uts/common/sys/scsi/scsi_pkt.h usr/src/uts/common/sys/scsi/targets/stdef.h |
diffstat | 7 files changed, 176 insertions(+), 17 deletions(-) [+] |
line wrap: on
line diff
--- a/usr/src/uts/common/io/scsi/adapters/mpt_sas/mptsas.c Wed Oct 07 17:26:56 2009 -0700 +++ b/usr/src/uts/common/io/scsi/adapters/mpt_sas/mptsas.c Thu Oct 08 10:37:32 2009 +0800 @@ -4829,7 +4829,7 @@ { uint8_t scsi_status, scsi_state; uint16_t ioc_status; - uint32_t xferred, sensecount, loginfo = 0; + uint32_t xferred, sensecount, responsedata, loginfo = 0; struct scsi_pkt *pkt; struct scsi_arq_status *arqstat; struct buf *bp; @@ -4848,6 +4848,8 @@ scsi_state = ddi_get8(mpt->m_acc_reply_frame_hdl, &reply->SCSIState); xferred = ddi_get32(mpt->m_acc_reply_frame_hdl, &reply->TransferCount); sensecount = ddi_get32(mpt->m_acc_reply_frame_hdl, &reply->SenseCount); + responsedata = ddi_get32(mpt->m_acc_reply_frame_hdl, + &reply->ResponseInfo); if (ioc_status & MPI2_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE) { loginfo = ddi_get32(mpt->m_acc_reply_frame_hdl, @@ -4887,6 +4889,16 @@ return; } + if (scsi_state & MPI2_SCSI_STATE_RESPONSE_INFO_VALID) { + responsedata &= 0x000000FF; + if (responsedata & MPTSAS_SCSI_RESPONSE_CODE_TLR_OFF) { + mptsas_log(mpt, CE_NOTE, "Do not support the TLR\n"); + pkt->pkt_reason = CMD_TLR_OFF; + return; + } + } + + switch (scsi_status) { case MPI2_SCSI_STATUS_CHECK_CONDITION: pkt->pkt_resid = (cmd->cmd_dmacount - xferred); @@ -7520,6 +7532,10 @@ control |= MPI2_SCSIIO_CONTROL_SIMPLEQ; } + if (cmd->cmd_pkt_flags & FLAG_TLR) { + control |= MPI2_SCSIIO_CONTROL_TLR_ON; + } + mem = mpt->m_req_frame + (mpt->m_req_frame_size * SMID); io_request = (pMpi2SCSIIORequest_t)mem; @@ -8618,6 +8634,13 @@ case SCSI_CAP_INTERCONNECT_TYPE: rval = INTERCONNECT_SAS; break; + case SCSI_CAP_TRAN_LAYER_RETRIES: + if (mpt->m_ioc_capabilities & + MPI2_IOCFACTS_CAPABILITY_TLR) + rval = TRUE; + else + rval = FALSE; + break; default: rval = UNDEFINED; break;
--- a/usr/src/uts/common/io/scsi/adapters/mpt_sas/mptsas_init.c Wed Oct 07 17:26:56 2009 -0700 +++ b/usr/src/uts/common/io/scsi/adapters/mpt_sas/mptsas_init.c Thu Oct 08 10:37:32 2009 +0800 @@ -267,6 +267,8 @@ */ mpt->m_max_chain_depth = ddi_get8(accessp, &factsreply->MaxChainDepth); + mpt->m_ioc_capabilities = ddi_get32(accessp, + &factsreply->IOCCapabilities); /* * Calculate max frames per request based on DMA S/G length.
--- a/usr/src/uts/common/io/scsi/targets/st.c Wed Oct 07 17:26:56 2009 -0700 +++ b/usr/src/uts/common/io/scsi/targets/st.c Thu Oct 08 10:37:32 2009 +0800 @@ -646,6 +646,10 @@ static void st_reset_notification(caddr_t arg); static const cmd_attribute *st_lookup_cmd_attribute(unsigned char cmd); +static int st_set_target_TLR_mode(struct scsi_tape *un, ubufunc_t ubf); +static int st_make_sure_mode_data_is_correct(struct scsi_tape *un, + ubufunc_t ubf); + #ifdef __x86 /* * routines for I/O in big block size @@ -1876,6 +1880,35 @@ } } + if (un->un_dp->type != ST_TYPE_INVALID) { + int result; + + /* try and enable TLR */ + un->un_tlr_flag = TLR_SAS_ONE_DEVICE; + result = st_set_target_TLR_mode(un, st_uscsi_cmd); + if (result == EACCES) { + /* + * From attach command failed. + * Set dp type so is run again on open. + */ + un->un_dp->type = ST_TYPE_INVALID; + un->un_tlr_flag = TLR_NOT_KNOWN; + } else if (result == 0) { + if (scsi_ifgetcap(&un->un_sd->sd_address, + "tran-layer-retries", 1) == -1) { + un->un_tlr_flag = TLR_NOT_SUPPORTED; + (void) st_set_target_TLR_mode(un, st_uscsi_cmd); + } else { + un->un_tlr_flag = TLR_SAS_ONE_DEVICE; + } + } else { + un->un_tlr_flag = TLR_NOT_SUPPORTED; + } + } + + + + /* * If we didn't just make up this configuration and * all the density codes are the same.. @@ -9062,6 +9095,7 @@ } else { pkt->pkt_comp = st_intr; } + st_add_recovery_info_to_pkt(un, bp, pkt); exit: ASSERT(mutex_owned(ST_MUTEX)); @@ -16866,11 +16900,7 @@ un->un_rsvd_status &= ~(ST_RELEASE | ST_LOST_RESERVE | ST_RESERVATION_CONFLICT | ST_INITIATED_RESET); } - rval = st_check_mode_for_change(un, st_uscsi_rcmd); - if (rval) { - rval = st_gen_mode_select(un, st_uscsi_rcmd, - un->un_mspl, sizeof (struct seq_mode)); - } + rval = st_make_sure_mode_data_is_correct(un, st_uscsi_rcmd); if (rval) { st_recov_ret(un, errinfo, COMMAND_DONE_ERROR); return; @@ -16887,14 +16917,8 @@ /* * See if mode sense changed. */ - rval = st_check_mode_for_change(un, st_uscsi_rcmd); - if (rval) { - /* - * If so change it back. - */ - rval = st_gen_mode_select(un, st_uscsi_rcmd, - un->un_mspl, sizeof (struct seq_mode)); - } + rval = st_make_sure_mode_data_is_correct(un, + st_uscsi_rcmd); if (rval) { st_recov_ret(un, errinfo, COMMAND_DONE_ERROR); return; @@ -17455,6 +17479,27 @@ } static int +st_make_sure_mode_data_is_correct(struct scsi_tape *un, ubufunc_t ubf) +{ + int rval; + + ST_FUNC(ST_DEVINFO, st_make_sure_mode_data_is_correct); + + /* + * check to see if mode data has changed. + */ + rval = st_check_mode_for_change(un, ubf); + if (rval) { + rval = st_gen_mode_select(un, ubf, un->un_mspl, + sizeof (struct seq_mode)); + } + if (un->un_tlr_flag != TLR_NOT_SUPPORTED) { + rval |= st_set_target_TLR_mode(un, ubf); + } + return (rval); +} + +static int st_check_mode_for_change(struct scsi_tape *un, ubufunc_t ubf) { struct seq_mode *current; @@ -18412,6 +18457,60 @@ return (rval); } +#define SAS_TLR_MOD_LEN sizeof (struct seq_mode) +static int +st_set_target_TLR_mode(struct scsi_tape *un, ubufunc_t ubf) +{ + int ret; + int amount = SAS_TLR_MOD_LEN; + struct seq_mode *mode_data; + + ST_FUNC(ST_DEVINFO, st_set_target_TLR_mode); + + mode_data = kmem_zalloc(SAS_TLR_MOD_LEN, KM_SLEEP); + ret = st_gen_mode_sense(un, ubf, 0x18, mode_data, amount); + if (ret != DDI_SUCCESS) { + if (ret != EACCES) + un->un_tlr_flag = TLR_NOT_SUPPORTED; + goto out; + } + if (mode_data->data_len != amount + 1) { + amount = mode_data->data_len + 1; + } + /* Must be SAS protocol */ + if (mode_data->page.saslun.protocol_id != 6) { + un->un_tlr_flag = TLR_NOT_SUPPORTED; + ret = ENOTSUP; + goto out; + } + if (un->un_tlr_flag == TLR_SAS_ONE_DEVICE) { + if (mode_data->page.saslun.tran_layer_ret == 1) + goto out; + mode_data->page.saslun.tran_layer_ret = 1; + } else { + if (mode_data->page.saslun.tran_layer_ret == 0) + goto out; + mode_data->page.saslun.tran_layer_ret = 0; + } + ret = st_gen_mode_select(un, ubf, mode_data, amount); + if (ret != DDI_SUCCESS) { + if (ret != EACCES) + un->un_tlr_flag = TLR_NOT_SUPPORTED; + } else { + if (mode_data->page.saslun.tran_layer_ret == 0) + un->un_tlr_flag = TLR_NOT_KNOWN; + else + un->un_tlr_flag = TLR_SAS_ONE_DEVICE; + } +#ifdef STDEBUG + st_clean_print(ST_DEVINFO, st_label, SCSI_DEBUG, "TLR data sent", + (char *)mode_data, amount); +#endif +out: + kmem_free(mode_data, SAS_TLR_MOD_LEN); + return (ret); +} + static void st_reset_notification(caddr_t arg)
--- a/usr/src/uts/common/sys/scsi/adapters/mpt_sas/mptsas_var.h Wed Oct 07 17:26:56 2009 -0700 +++ b/usr/src/uts/common/sys/scsi/adapters/mpt_sas/mptsas_var.h Thu Oct 08 10:37:32 2009 +0800 @@ -725,6 +725,7 @@ uint32_t m_free_index; uint32_t m_post_index; uint8_t m_reply_frame_size; + uint32_t m_ioc_capabilities; /* * indicates if the firmware was upload by the driver @@ -1135,6 +1136,11 @@ #define MPTSAS_CMD_TIMEOUT 0x0010 /* + * response code tlr flag + */ +#define MPTSAS_SCSI_RESPONSE_CODE_TLR_OFF 0x02 + +/* * System Events */ #ifndef DDI_VENDOR_LSI
--- a/usr/src/uts/common/sys/scsi/impl/services.h Wed Oct 07 17:26:56 2009 -0700 +++ b/usr/src/uts/common/sys/scsi/impl/services.h Thu Oct 08 10:37:32 2009 +0800 @@ -127,6 +127,7 @@ #define SCSI_CAP_LUN_RESET 19 #define SCSI_CAP_CDB_LEN 20 #define SCSI_CAP_DMA_MAX_ARCH 21 +#define SCSI_CAP_TRAN_LAYER_RETRIES 22 #define SCSI_CAP_ASCII { \ "dma-max", "msg-out", "disconnect", "synchronous", \ "wide-xfer", "parity", "initiator-id", "untagged-qing", \ @@ -135,7 +136,8 @@ "reset-notification", "qfull-retries", \ "qfull-retry-interval", "scsi-version", \ "interconnect-type", "lun-reset", \ - "max-cdb-length", "dma-max-arch", NULL } + "max-cdb-length", "dma-max-arch", \ + "tran-layer-retries", NULL } /* * Definitions used by some capabilities
--- a/usr/src/uts/common/sys/scsi/scsi_pkt.h Wed Oct 07 17:26:56 2009 -0700 +++ b/usr/src/uts/common/sys/scsi/scsi_pkt.h Thu Oct 08 10:37:32 2009 +0800 @@ -163,6 +163,12 @@ #define FLAG_ISOLATE 0x00040000 /* + * pkg_flag for TLR + */ +#define FLAG_TLR 0x00080000 + + +/* * Following define is for scsi_vhci. * NOQUEUE If pHCI cannot transport the command to the device, * do not queue the pkt in pHCI. Return immediately with @@ -194,6 +200,7 @@ #define CMD_CMD_OVR 8 /* Command Overrun */ #define CMD_STS_OVR 9 /* Status Overrun */ #define CMD_TERMINATED 22 /* Command transport terminated on request */ +#define CMD_TLR_OFF 23 /* don't support TLR */ /* * Following defines are appropriate for SCSI parallel bus.
--- a/usr/src/uts/common/sys/scsi/targets/stdef.h Wed Oct 07 17:26:56 2009 -0700 +++ b/usr/src/uts/common/sys/scsi/targets/stdef.h Thu Oct 08 10:37:32 2009 +0800 @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -508,9 +508,23 @@ #endif }; +struct sas_lun_mode { +#if defined(_BIT_FIELDS_HTOL) + uchar_t : 3, + tran_layer_ret: 1, + protocol_id: 4; + uchar_t reserved[5]; +#elif defined(_BIT_FIELDS_LTOH) + uchar_t protocol_id: 4, + tran_layer_ret: 1, + : 3; + uchar_t reserved[5]; +#endif +}; typedef union { struct comp_mode_page comp; struct dev_mode_page dev; + struct sas_lun_mode saslun; }modepage; /* @@ -926,6 +940,12 @@ }st_states; typedef enum { RDWR, RDONLY, WORM, RDWORM, FAILED } writablity; +typedef enum { + TLR_NOT_KNOWN, + TLR_NOT_SUPPORTED, + TLR_SAS_ONE_DEVICE, + TLR_SAS_TWO_DEVICE +}st_tlr_state; /* @@ -1023,7 +1043,6 @@ read_pos_data_t *un_read_pos_data; struct mterror_entry_stack *un_error_entry_stk; /* latest sense cmd buffer */ - #ifdef __x86 ddi_dma_handle_t un_contig_mem_hdl; struct contig_mem *un_contig_mem; @@ -1048,6 +1067,7 @@ uchar_t un_unit_attention_flags; uchar_t un_multipath; ulong_t un_last_path_instance; + st_tlr_state un_tlr_flag; /* tape support TLR flag */ }; typedef int (*bufunc_t)(struct scsi_tape *, int, int64_t, int);