diff options
author | Pawel Wojcik <Pawel.Wojcik@Sun.COM> | 2008-09-08 14:07:52 -0700 |
---|---|---|
committer | Pawel Wojcik <Pawel.Wojcik@Sun.COM> | 2008-09-08 14:07:52 -0700 |
commit | 3852f6739b148db36d43cd6e758a0855fd49f24c (patch) | |
tree | 699d293b324b86e0e4c4a6f16b3bf19492583e06 /usr/src | |
parent | 0068372b94fa8832a6e2897de3239ff2b7b2c6b9 (diff) | |
download | illumos-joyent-3852f6739b148db36d43cd6e758a0855fd49f24c.tar.gz |
6681317 sata module should reject scsi packets that may be executed synchronously in the interrupt context
6733438 sata module SMART and LOG related functions should have more informational headers
Diffstat (limited to 'usr/src')
-rw-r--r-- | usr/src/uts/common/io/sata/impl/sata.c | 110 | ||||
-rw-r--r-- | usr/src/uts/common/sys/sata/impl/sata.h | 5 |
2 files changed, 105 insertions, 10 deletions
diff --git a/usr/src/uts/common/io/sata/impl/sata.c b/usr/src/uts/common/io/sata/impl/sata.c index f4e7344e18..3385f429dd 100644 --- a/usr/src/uts/common/io/sata/impl/sata.c +++ b/usr/src/uts/common/io/sata/impl/sata.c @@ -24,7 +24,6 @@ * Use is subject to license terms. */ -#pragma ident "%Z%%M% %I% %E% SMI" /* * SATA Framework @@ -45,6 +44,7 @@ #include <sys/sysevent/eventdefs.h> #include <sys/sysevent/dr.h> #include <sys/taskq.h> +#include <sys/disp.h> #include <sys/sata/impl/sata.h> #include <sys/sata/sata_hba.h> @@ -127,6 +127,8 @@ static void sata_inject_pkt_fault(sata_pkt_t *, uint8_t, int *, int); #define LEGACY_HWID_LEN 64 /* Model (40) + Serial (20) + pad */ +static char sata_rev_tag[] = {"1.37"}; + /* * SATA cb_ops functions */ @@ -368,7 +370,7 @@ extern uchar_t scsi_cdb_size[]; static struct modlmisc modlmisc = { &mod_miscops, /* Type of module */ - "SATA Module v%I%" /* module name */ + "SATA Module" /* module name */ }; @@ -2769,6 +2771,18 @@ sata_txlt_generic_pkt_info(sata_pkt_txlate_t *spx, int *reason) /* all OK; pkt reason will be overwritten later */ break; } + /* + * If in an interrupt context, reject packet if it is to be + * executed in polling mode + */ + if (servicing_interrupt() && + (spx->txlt_scsi_pkt->pkt_flags & FLAG_NOINTR) != 0) { + SATADBG1(SATA_DBG_INTR_CTX, spx->txlt_sata_hba_inst, + "sata_scsi_start: rejecting synchronous command because " + "of interrupt context\n", NULL); + return (TRAN_BUSY); + } + sdinfo = sata_get_device_info(spx->txlt_sata_hba_inst, &spx->txlt_sata_pkt->satapkt_device); @@ -3212,6 +3226,12 @@ done: * Always NO SENSE, because any sense data should be reported by ARQ sense. * * Returns TRAN_ACCEPT and appropriate values in scsi_pkt fields. + * + * Note: There is a mismatch between already implemented Informational + * Exception Mode Select page 0x1C and this function. + * When MRIE bit is set in page 0x1C, Request Sense is supposed to return + * NO SENSE and set additional sense code to the exception code - this is not + * implemented here. */ static int sata_txlt_request_sense(sata_pkt_txlate_t *spx) @@ -3811,11 +3831,15 @@ done: * by mode select pages. The first error terminates further execution. * Operations performed successully are not backed-up in such case. * - * NOTE: only caching mode select page is implemented. + * NOTE: Implemented pages: + * - caching page + * - informational exception page + * - acoustic management page * Caching setup is remembered so it could be re-stored in case of * an unexpected device reset. * - * Returns TRAN_ACCEPT and appropriate values in scsi_pkt fields. + * Returns TRAN_XXXX. + * If TRAN_ACCEPT is returned, appropriate values are set in scsi_pkt fields. */ static int @@ -3842,6 +3866,17 @@ sata_txlt_mode_select(sata_pkt_txlate_t *spx) mutex_exit(&(SATA_TXLT_CPORT_MUTEX(spx))); return (rval); } + /* + * If in interrupt context, reject this packet because it may result + * in issuing a synchronous command to HBA. + */ + if (servicing_interrupt()) { + SATADBG1(SATA_DBG_INTR_CTX, spx->txlt_sata_hba_inst, + "sata_txlt_mode_select: rejecting command because " + "of interrupt context\n", NULL); + mutex_exit(&(SATA_TXLT_CPORT_MUTEX(spx))); + return (TRAN_BUSY); + } rval = TRAN_ACCEPT; @@ -4122,6 +4157,18 @@ sata_txlt_log_sense(sata_pkt_txlate_t *spx) kmem_free(buf, MAX_LOG_SENSE_PAGE_SIZE); return (rval); } + /* + * If in interrupt context, reject this packet because it may result + * in issuing a synchronous command to HBA. + */ + if (servicing_interrupt()) { + SATADBG1(SATA_DBG_INTR_CTX, spx->txlt_sata_hba_inst, + "sata_log_sense: rejecting command because " + "of interrupt context\n", NULL); + mutex_exit(&(SATA_TXLT_CPORT_MUTEX(spx))); + kmem_free(buf, MAX_LOG_SENSE_PAGE_SIZE); + return (TRAN_BUSY); + } scsipkt->pkt_reason = CMD_CMPLT; scsipkt->pkt_state = STATE_GOT_BUS | STATE_GOT_TARGET | @@ -4180,7 +4227,6 @@ sata_txlt_log_sense(sata_pkt_txlate_t *spx) spx->txlt_sata_hba_inst, &spx->txlt_sata_pkt->satapkt_device); - /* * Add requested pages. */ @@ -4890,6 +4936,16 @@ sata_txlt_write_buffer(sata_pkt_txlate_t *spx) mutex_exit(&(SATA_TXLT_CPORT_MUTEX(spx))); return (rval); } + /* + * If in interrupt context, reject this packet because it would issue + * a synchronous command to HBA. + */ + if (servicing_interrupt()) { + SATADBG1(SATA_DBG_INTR_CTX, spx->txlt_sata_hba_inst, + "sata_txlt_write_buffer: rejecting command because " + "of interrupt context\n", NULL); + return (TRAN_BUSY); + } /* Use synchronous mode */ spx->txlt_sata_pkt->satapkt_op_mode @@ -6077,6 +6133,7 @@ sata_mode_select_page_8(sata_pkt_txlate_t *spx, struct mode_cache_scsi3 *page, *rval = TRAN_ACCEPT; return (SATA_SUCCESS); } + /* * Need to flip some setting * Set-up Internal SET FEATURES command(s) @@ -6155,8 +6212,15 @@ failure: * The only changeable bit is dexcpt (disable exceptions). * MRIE (method of reporting informational exceptions) must be * "only on request". - * - * Return SATA_SUCCESS if operation succeeded, SATA_FAILURE otherwise. + * This page applies to informational exceptions that report + * additional sense codes with the ADDITIONAL SENSE CODE field set to 5Dh + * (e.g.,FAILURE PREDICTION THRESHOLD EXCEEDED) or 0Bh (e.g., WARNING_). + * Informational exception conditions occur as the result of background scan + * errors, background self-test errors, or vendor specific events within a + * logical unit. An informational exception condition may occur asynchronous + * to any commands. + * + * Returns: SATA_SUCCESS if operation succeeded, SATA_FAILURE otherwise. * If operation resulted in changing device setup, dmod flag should be set to * one (1). If parameters were not changed, dmod flag should be set to 0. * Upon return, if operation required sending command to the device, the rval @@ -6167,6 +6231,8 @@ failure: * This function has to be called with a port mutex held. * * Returns SATA_SUCCESS if operation was successful, SATA_FAILURE otherwise. + * + * Cannot be called in the interrupt context. */ static int sata_mode_select_page_1c( @@ -6250,6 +6316,16 @@ sata_mode_select_page_1c( return (SATA_FAILURE); } +/* + * Process mode select acoustic management control page 0x30 + * + * + * This function has to be called with a port mutex held. + * + * Returns SATA_SUCCESS if operation was successful, SATA_FAILURE otherwise. + * + * Cannot be called in the interrupt context. + */ int sata_mode_select_page_30(sata_pkt_txlate_t *spx, struct mode_acoustic_management *page, int parmlen, int *pagelen, @@ -6375,6 +6451,19 @@ sata_build_lsense_page_0(sata_drive_info_t *sdinfo, uint8_t *buf) * in which to create the page information as well as a sata_hba_inst_t *. * * Returns the number of bytes valid in the buffer. + * + * Note: Self test and SMART data is accessible in device log pages. + * The log pages can be accessed by SMART READ/WRITE LOG (up to 255 sectors + * of data can be transferred by a single command), or by the General Purpose + * Logging commands (GPL) READ LOG EXT and WRITE LOG EXT (up to 65,535 sectors + * - approximately 33MB - can be transferred by a single command. + * The SCT Command response (either error or command) is the same for both + * the SMART and GPL methods of issuing commands. + * This function uses READ LOG EXT command when drive supports LBA48, and + * SMART READ command otherwise. + * + * Since above commands are executed in a synchronous mode, this function + * should not be called in an interrupt context. */ static int sata_build_lsense_page_10( @@ -6774,12 +6863,15 @@ done: /* * sata_build_lsense_page_2f() is used to create the - * SCSI LOG SENSE page 0x10 (informational exceptions) + * SCSI LOG SENSE page 0x2f (informational exceptions) * * Takes a sata_drive_info t * and the address of a buffer * in which to create the page information as well as a sata_hba_inst_t *. * * Returns the number of bytes valid in the buffer. + * + * Because it invokes function(s) that send synchronously executed command + * to the HBA, it cannot be called in the interrupt context. */ static int sata_build_lsense_page_2f( @@ -12997,6 +13089,8 @@ fail: /* * Used by LOG SENSE page 0x10 + * Reads (in synchronous mode) the self test log data using Read Log Ext cmd. + * Note: cannot be called in the interrupt context. * * return 0 for success, -1 otherwise * diff --git a/usr/src/uts/common/sys/sata/impl/sata.h b/usr/src/uts/common/sys/sata/impl/sata.h index 18c86d23a4..ce329bb5c3 100644 --- a/usr/src/uts/common/sys/sata/impl/sata.h +++ b/usr/src/uts/common/sys/sata/impl/sata.h @@ -27,8 +27,6 @@ #ifndef _SATA_H #define _SATA_H -#pragma ident "%Z%%M% %I% %E% SMI" - #ifdef __cplusplus extern "C" { #endif @@ -733,6 +731,7 @@ _NOTE(SCHEME_PROTECTS_DATA("unshared data", scsi_pkt)) #define SATA_DBG_DEV_SETTINGS 0x800 #define SATA_DBG_ATAPI 0x1000 #define SATA_DBG_ATAPI_PACKET 0x8000 +#define SATA_DBG_INTR_CTX 0x10000 typedef struct sata_atapi_cmd { uint8_t acdb[SATA_ATAPI_MAX_CDB_LEN]; @@ -764,6 +763,8 @@ typedef struct sata_atapi_cmd { #endif +/* sata_rev_tag 1.37 */ + #ifdef __cplusplus } #endif |