summaryrefslogtreecommitdiff
path: root/usr/src
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src')
-rw-r--r--usr/src/uts/common/io/sata/impl/sata.c110
-rw-r--r--usr/src/uts/common/sys/sata/impl/sata.h5
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