summaryrefslogtreecommitdiff
path: root/usr/src/uts/common
diff options
context:
space:
mode:
authorKeith M Wesolowski <wesolows@foobazco.org>2014-04-30 17:33:08 +0000
committerKeith M Wesolowski <wesolows@foobazco.org>2014-04-30 17:33:08 +0000
commite5eca69f4b721e7e2209d18b3358d79069be9024 (patch)
tree10281da4c59357b0ca0f9a89d716be080ed4c7ab /usr/src/uts/common
parente7a35eac19dab0d7a03157433255ec4d9ee9c60a (diff)
parent19449258028e6813f0b7a606b554b2fa37a390ec (diff)
downloadillumos-joyent-e5eca69f4b721e7e2209d18b3358d79069be9024.tar.gz
[illumos-gate merge]
commit 19449258028e6813f0b7a606b554b2fa37a390ec 4823 don't open-code NSEC2MSEC and MSEC2NSEC commit cb3e7fb42f8104f779abb6856ccf6e5b8e6419d8 4819 fix mpt_sas command timeout handling commit b59e2127f21675e88c58a4dd924bc55eeb83c7a6 4809 NANOSEC should be 'long long' to avoid integer overflow bugs 4810 spa_async_tasks_pending suffers from an integer overflow bug 4811 in.mpathd: tv2ns suffers from an integer overflow bug
Diffstat (limited to 'usr/src/uts/common')
-rw-r--r--usr/src/uts/common/dtrace/dtrace.c2
-rw-r--r--usr/src/uts/common/inet/ip/ip.c8
-rw-r--r--usr/src/uts/common/io/devpoll.c2
-rw-r--r--usr/src/uts/common/io/power.c2
-rw-r--r--usr/src/uts/common/io/scsi/adapters/mpt_sas/mptsas.c279
-rw-r--r--usr/src/uts/common/sys/scsi/adapters/mpt_sas/mptsas_var.h16
-rw-r--r--usr/src/uts/common/sys/time.h2
7 files changed, 167 insertions, 144 deletions
diff --git a/usr/src/uts/common/dtrace/dtrace.c b/usr/src/uts/common/dtrace/dtrace.c
index 3ecd33e24e..e52b51315c 100644
--- a/usr/src/uts/common/dtrace/dtrace.c
+++ b/usr/src/uts/common/dtrace/dtrace.c
@@ -139,7 +139,7 @@ dtrace_optval_t dtrace_ustackframes_default = 20;
dtrace_optval_t dtrace_jstackframes_default = 50;
dtrace_optval_t dtrace_jstackstrsize_default = 512;
int dtrace_msgdsize_max = 128;
-hrtime_t dtrace_chill_max = 500 * (NANOSEC / MILLISEC); /* 500 ms */
+hrtime_t dtrace_chill_max = MSEC2NSEC(500); /* 500 ms */
hrtime_t dtrace_chill_interval = NANOSEC; /* 1000 ms */
int dtrace_devdepth_max = 32;
int dtrace_err_verbose;
diff --git a/usr/src/uts/common/inet/ip/ip.c b/usr/src/uts/common/inet/ip/ip.c
index 313c6120ed..4b65ec8a6d 100644
--- a/usr/src/uts/common/inet/ip/ip.c
+++ b/usr/src/uts/common/inet/ip/ip.c
@@ -1498,7 +1498,7 @@ icmp_inbound_v4(mblk_t *mp, ip_recv_attr_t *ira)
/* Compute # of milliseconds since midnight */
gethrestime(&now);
ts = (now.tv_sec % (24 * 60 * 60)) * 1000 +
- now.tv_nsec / (NANOSEC / MILLISEC);
+ NSEC2MSEC(now.tv_nsec);
*tsp++ = htonl(ts); /* Lay in 'receive time' */
*tsp++ = htonl(ts); /* Lay in 'send time' */
BUMP_MIB(&ipst->ips_icmp_mib, icmpOutTimestampReps);
@@ -9117,7 +9117,7 @@ ip_forward_options(mblk_t *mp, ipha_t *ipha, ill_t *dst_ill,
/* Compute # of milliseconds since midnight */
gethrestime(&now);
ts = (now.tv_sec % (24 * 60 * 60)) * 1000 +
- now.tv_nsec / (NANOSEC / MILLISEC);
+ NSEC2MSEC(now.tv_nsec);
bcopy(&ts, (char *)opt + off, IPOPT_TS_TIMELEN);
opt[IPOPT_OFFSET] += IPOPT_TS_TIMELEN;
break;
@@ -9343,7 +9343,7 @@ ip_input_local_options(mblk_t *mp, ipha_t *ipha, ip_recv_attr_t *ira)
/* Compute # of milliseconds since midnight */
gethrestime(&now);
ts = (now.tv_sec % (24 * 60 * 60)) * 1000 +
- now.tv_nsec / (NANOSEC / MILLISEC);
+ NSEC2MSEC(now.tv_nsec);
bcopy(&ts, (char *)opt + off, IPOPT_TS_TIMELEN);
opt[IPOPT_OFFSET] += IPOPT_TS_TIMELEN;
break;
@@ -12025,7 +12025,7 @@ ip_output_local_options(ipha_t *ipha, ip_stack_t *ipst)
/* Compute # of milliseconds since midnight */
gethrestime(&now);
ts = (now.tv_sec % (24 * 60 * 60)) * 1000 +
- now.tv_nsec / (NANOSEC / MILLISEC);
+ NSEC2MSEC(now.tv_nsec);
bcopy(&ts, (char *)opt + off, IPOPT_TS_TIMELEN);
opt[IPOPT_OFFSET] += IPOPT_TS_TIMELEN;
break;
diff --git a/usr/src/uts/common/io/devpoll.c b/usr/src/uts/common/io/devpoll.c
index 3c1e80eb01..db6d4881d4 100644
--- a/usr/src/uts/common/io/devpoll.c
+++ b/usr/src/uts/common/io/devpoll.c
@@ -960,7 +960,7 @@ dpioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *credp, int *rvalp)
* to absolute nanoseconds. They must wait for at
* least a tick.
*/
- deadline = deadline * NANOSEC / MILLISEC;
+ deadline = MSEC2NSEC(deadline);
deadline = MAX(deadline, nsec_per_tick);
deadline += now;
}
diff --git a/usr/src/uts/common/io/power.c b/usr/src/uts/common/io/power.c
index 61e675ba77..aed53f5334 100644
--- a/usr/src/uts/common/io/power.c
+++ b/usr/src/uts/common/io/power.c
@@ -116,7 +116,7 @@ static char hasEPIC = B_FALSE;
static void *power_state;
static int power_inst = -1;
-static hrtime_t power_button_debounce = NANOSEC/MILLISEC*10;
+static hrtime_t power_button_debounce = MSEC2NSEC(10);
static hrtime_t power_button_abort_interval = 1.5 * NANOSEC;
static int power_button_abort_presses = 3;
static int power_button_abort_enable = 1;
diff --git a/usr/src/uts/common/io/scsi/adapters/mpt_sas/mptsas.c b/usr/src/uts/common/io/scsi/adapters/mpt_sas/mptsas.c
index a21e8c820f..e7ad12761c 100644
--- a/usr/src/uts/common/io/scsi/adapters/mpt_sas/mptsas.c
+++ b/usr/src/uts/common/io/scsi/adapters/mpt_sas/mptsas.c
@@ -21,7 +21,7 @@
/*
* Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright 2012 Nexenta Systems, Inc. All rights reserved.
+ * Copyright 2014 Nexenta Systems, Inc. All rights reserved.
* Copyright (c) 2014, Joyent, Inc. All rights reserved.
* Copyright 2014 OmniTI Computer Consulting, Inc. All rights reserved.
*/
@@ -240,7 +240,7 @@ static void mptsas_sge_setup(mptsas_t *mpt, mptsas_cmd_t *cmd,
static void mptsas_watch(void *arg);
static void mptsas_watchsubr(mptsas_t *mpt);
-static void mptsas_cmd_timeout(mptsas_t *mpt, uint16_t devhdl);
+static void mptsas_cmd_timeout(mptsas_t *mpt, mptsas_target_t *ptgt);
static void mptsas_start_passthru(mptsas_t *mpt, mptsas_cmd_t *cmd);
static int mptsas_do_passthru(mptsas_t *mpt, uint8_t *request, uint8_t *reply,
@@ -3379,17 +3379,17 @@ mptsas_save_cmd(mptsas_t *mpt, mptsas_cmd_t *cmd)
* event acknoledgment)
*/
if ((cmd->cmd_flags & CFLAG_CMDIOC) == 0) {
+ /*
+ * Expiration time is set in mptsas_start_cmd
+ */
ptgt->m_t_ncmds++;
- }
- cmd->cmd_active_timeout = cmd->cmd_pkt->pkt_time;
-
- /*
- * If initial timout is less than or equal to one tick, bump
- * the timeout by a tick so that command doesn't timeout before
- * its allotted time.
- */
- if (cmd->cmd_active_timeout <= mptsas_scsi_watchdog_tick) {
- cmd->cmd_active_timeout += mptsas_scsi_watchdog_tick;
+ cmd->cmd_active_expiration = 0;
+ } else {
+ /*
+ * Initialize expiration time for passthrough commands,
+ */
+ cmd->cmd_active_expiration = gethrtime() +
+ (hrtime_t)cmd->cmd_pkt->pkt_time * NANOSEC;
}
return (TRUE);
}
@@ -4853,9 +4853,8 @@ mptsas_handle_address_reply(mptsas_t *mpt,
"reply in slot %d", SMID);
return;
}
- if ((cmd->cmd_flags & CFLAG_PASSTHRU) ||
- (cmd->cmd_flags & CFLAG_CONFIG) ||
- (cmd->cmd_flags & CFLAG_FW_DIAG)) {
+ if ((cmd->cmd_flags &
+ (CFLAG_PASSTHRU | CFLAG_CONFIG | CFLAG_FW_DIAG))) {
cmd->cmd_rfm = reply_addr;
cmd->cmd_flags |= CFLAG_FINISHED;
cv_broadcast(&mpt->m_passthru_cv);
@@ -5022,6 +5021,9 @@ mptsas_check_scsi_io_error(mptsas_t *mpt, pMpi2SCSIIOReply_t reply,
struct buf *bp;
mptsas_target_t *ptgt = cmd->cmd_tgt_addr;
uint8_t *sensedata = NULL;
+ uint64_t sas_wwn;
+ uint8_t phy;
+ char wwn_str[MPTSAS_WWN_STRLEN];
if ((cmd->cmd_flags & (CFLAG_SCBEXTERN | CFLAG_EXTARQBUFVALID)) ==
(CFLAG_SCBEXTERN | CFLAG_EXTARQBUFVALID)) {
@@ -5039,12 +5041,19 @@ mptsas_check_scsi_io_error(mptsas_t *mpt, pMpi2SCSIIOReply_t reply,
&reply->ResponseInfo);
if (ioc_status & MPI2_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE) {
+ sas_wwn = ptgt->m_addr.mta_wwn;
+ phy = ptgt->m_phynum;
+ if (sas_wwn == 0) {
+ (void) sprintf(wwn_str, "p%x", phy);
+ } else {
+ (void) sprintf(wwn_str, "w%016"PRIx64, sas_wwn);
+ }
loginfo = ddi_get32(mpt->m_acc_reply_frame_hdl,
&reply->IOCLogInfo);
mptsas_log(mpt, CE_NOTE,
- "?Log info 0x%x received for target %d.\n"
+ "?Log info 0x%x received for target %d %s.\n"
"\tscsi_status=0x%x, ioc_status=0x%x, scsi_state=0x%x",
- loginfo, Tgt(cmd), scsi_status, ioc_status,
+ loginfo, Tgt(cmd), wwn_str, scsi_status, ioc_status,
scsi_state);
}
@@ -5199,8 +5208,18 @@ mptsas_check_scsi_io_error(mptsas_t *mpt, pMpi2SCSIIOReply_t reply,
}
break;
case MPI2_IOCSTATUS_SCSI_TASK_TERMINATED:
- mptsas_set_pkt_reason(mpt,
- cmd, CMD_RESET, STAT_BUS_RESET);
+ if (cmd->cmd_active_expiration <= gethrtime()) {
+ /*
+ * When timeout requested, propagate
+ * proper reason and statistics to
+ * target drivers.
+ */
+ mptsas_set_pkt_reason(mpt, cmd, CMD_TIMEOUT,
+ STAT_BUS_RESET | STAT_TIMEOUT);
+ } else {
+ mptsas_set_pkt_reason(mpt, cmd, CMD_RESET,
+ STAT_BUS_RESET);
+ }
break;
case MPI2_IOCSTATUS_SCSI_IOC_TERMINATED:
case MPI2_IOCSTATUS_SCSI_EXT_TERMINATED:
@@ -7660,7 +7679,6 @@ mptsas_remove_cmd(mptsas_t *mpt, mptsas_cmd_t *cmd)
{
int slot;
mptsas_slots_t *slots = mpt->m_active;
- int t;
mptsas_target_t *ptgt = cmd->cmd_tgt_addr;
ASSERT(cmd != NULL);
@@ -7674,7 +7692,6 @@ mptsas_remove_cmd(mptsas_t *mpt, mptsas_cmd_t *cmd)
return;
}
- t = Tgt(cmd);
slot = cmd->cmd_slot;
/*
@@ -7699,8 +7716,16 @@ mptsas_remove_cmd(mptsas_t *mpt, mptsas_cmd_t *cmd)
((cmd->cmd_pkt_flags & FLAG_TAGMASK) == 0)) {
mptsas_set_throttle(mpt, ptgt, MAX_THROTTLE);
}
- }
+ /*
+ * Remove this command from the active queue.
+ */
+ if (cmd->cmd_active_expiration != 0) {
+ TAILQ_REMOVE(&ptgt->m_active_cmdq, cmd,
+ cmd_active_link);
+ cmd->cmd_active_expiration = 0;
+ }
+ }
}
/*
@@ -7711,50 +7736,6 @@ mptsas_remove_cmd(mptsas_t *mpt, mptsas_cmd_t *cmd)
return;
}
- /*
- * Figure out what to set tag Q timeout for...
- *
- * Optimize: If we have duplicate's of same timeout
- * we're using, then we'll use it again until we run
- * out of duplicates. This should be the normal case
- * for block and raw I/O.
- * If no duplicates, we have to scan through tag que and
- * find the longest timeout value and use it. This is
- * going to take a while...
- * Add 1 to m_n_normal to account for TM request.
- */
- if (cmd->cmd_pkt->pkt_time == ptgt->m_timebase) {
- if (--(ptgt->m_dups) == 0) {
- if (ptgt->m_t_ncmds) {
- mptsas_cmd_t *ssp;
- uint_t n = 0;
- ushort_t nslots = (slots->m_n_normal + 1);
- ushort_t i;
- /*
- * This crude check assumes we don't do
- * this too often which seems reasonable
- * for block and raw I/O.
- */
- for (i = 0; i < nslots; i++) {
- ssp = slots->m_slot[i];
- if (ssp && (Tgt(ssp) == t) &&
- (ssp->cmd_pkt->pkt_time > n)) {
- n = ssp->cmd_pkt->pkt_time;
- ptgt->m_dups = 1;
- } else if (ssp && (Tgt(ssp) == t) &&
- (ssp->cmd_pkt->pkt_time == n)) {
- ptgt->m_dups++;
- }
- }
- ptgt->m_timebase = n;
- } else {
- ptgt->m_dups = 0;
- ptgt->m_timebase = 0;
- }
- }
- }
- ptgt->m_timeout = ptgt->m_timebase;
-
ASSERT(cmd != slots->m_slot[cmd->cmd_slot]);
}
@@ -7909,7 +7890,6 @@ mptsas_start_cmd(mptsas_t *mpt, mptsas_cmd_t *cmd)
{
struct scsi_pkt *pkt = CMD2PKT(cmd);
uint32_t control = 0;
- int n;
caddr_t mem;
pMpi2SCSIIORequest_t io_request;
ddi_dma_handle_t dma_hdl = mpt->m_dma_req_frame_hdl;
@@ -7917,6 +7897,7 @@ mptsas_start_cmd(mptsas_t *mpt, mptsas_cmd_t *cmd)
mptsas_target_t *ptgt = cmd->cmd_tgt_addr;
uint16_t SMID, io_flags = 0;
uint32_t request_desc_low, request_desc_high;
+ mptsas_cmd_t *c;
NDBG1(("mptsas_start_cmd: cmd=0x%p", (void *)cmd));
@@ -8046,37 +8027,44 @@ mptsas_start_cmd(mptsas_t *mpt, mptsas_cmd_t *cmd)
/*
* Start timeout.
*/
+ cmd->cmd_active_expiration =
+ gethrtime() + (hrtime_t)pkt->pkt_time * NANOSEC;
#ifdef MPTSAS_TEST
/*
- * Temporarily set timebase = 0; needed for
- * timeout torture test.
+ * Force timeouts to happen immediately.
*/
- if (mptsas_test_timeouts) {
- ptgt->m_timebase = 0;
- }
+ if (mptsas_test_timeouts)
+ cmd->cmd_active_expiration = gethrtime();
#endif
- n = pkt->pkt_time - ptgt->m_timebase;
-
- if (n == 0) {
- (ptgt->m_dups)++;
- ptgt->m_timeout = ptgt->m_timebase;
- } else if (n > 0) {
- ptgt->m_timeout =
- ptgt->m_timebase = pkt->pkt_time;
- ptgt->m_dups = 1;
- } else if (n < 0) {
- ptgt->m_timeout = ptgt->m_timebase;
- }
-#ifdef MPTSAS_TEST
- /*
- * Set back to a number higher than
- * mptsas_scsi_watchdog_tick
- * so timeouts will happen in mptsas_watchsubr
- */
- if (mptsas_test_timeouts) {
- ptgt->m_timebase = 60;
+ c = TAILQ_FIRST(&ptgt->m_active_cmdq);
+ if (c == NULL ||
+ c->cmd_active_expiration < cmd->cmd_active_expiration) {
+ /*
+ * Common case is that this is the last pending expiration
+ * (or queue is empty). Insert at head of the queue.
+ */
+ TAILQ_INSERT_HEAD(&ptgt->m_active_cmdq, cmd, cmd_active_link);
+ } else {
+ /*
+ * Queue is not empty and first element expires later than
+ * this command. Search for element expiring sooner.
+ */
+ while ((c = TAILQ_NEXT(c, cmd_active_link)) != NULL) {
+ if (c->cmd_active_expiration <
+ cmd->cmd_active_expiration) {
+ TAILQ_INSERT_BEFORE(c, cmd, cmd_active_link);
+ break;
+ }
+ }
+ if (c == NULL) {
+ /*
+ * No element found expiring sooner, append to
+ * non-empty queue.
+ */
+ TAILQ_INSERT_TAIL(&ptgt->m_active_cmdq, cmd,
+ cmd_active_link);
+ }
}
-#endif
if ((mptsas_check_dma_handle(dma_hdl) != DDI_SUCCESS) ||
(mptsas_check_acc_handle(acc_hdl) != DDI_SUCCESS)) {
@@ -8590,9 +8578,12 @@ mptsas_flush_target(mptsas_t *mpt, ushort_t target, int lun, uint8_t tasktype)
int slot;
uchar_t reason;
uint_t stat;
+ hrtime_t timestamp;
NDBG25(("mptsas_flush_target: target=%d lun=%d", target, lun));
+ timestamp = gethrtime();
+
/*
* Make sure the I/O Controller has flushed all cmds
* that are associated with this target for a target reset
@@ -8607,6 +8598,15 @@ mptsas_flush_target(mptsas_t *mpt, ushort_t target, int lun, uint8_t tasktype)
switch (tasktype) {
case MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET:
if (Tgt(cmd) == target) {
+ if (cmd->cmd_active_expiration <= timestamp) {
+ /*
+ * When timeout requested, propagate
+ * proper reason and statistics to
+ * target drivers.
+ */
+ reason = CMD_TIMEOUT;
+ stat |= STAT_TIMEOUT;
+ }
NDBG25(("mptsas_flush_target discovered non-"
"NULL cmd in slot %d, tasktype 0x%x", slot,
tasktype));
@@ -8746,9 +8746,8 @@ mptsas_flush_hba(mptsas_t *mpt)
*/
mptsas_set_pkt_reason(mpt, cmd, CMD_RESET,
STAT_BUS_RESET);
- if ((cmd->cmd_flags & CFLAG_PASSTHRU) ||
- (cmd->cmd_flags & CFLAG_CONFIG) ||
- (cmd->cmd_flags & CFLAG_FW_DIAG)) {
+ if ((cmd->cmd_flags &
+ (CFLAG_PASSTHRU | CFLAG_CONFIG | CFLAG_FW_DIAG))) {
cmd->cmd_flags |= CFLAG_FINISHED;
cv_broadcast(&mpt->m_passthru_cv);
cv_broadcast(&mpt->m_config_cv);
@@ -9390,6 +9389,7 @@ mptsas_watchsubr(mptsas_t *mpt)
int i;
mptsas_cmd_t *cmd;
mptsas_target_t *ptgt = NULL;
+ hrtime_t timestamp = gethrtime();
ASSERT(MUTEX_HELD(&mpt->m_mutex));
@@ -9407,10 +9407,8 @@ mptsas_watchsubr(mptsas_t *mpt)
*/
for (i = 0; i <= mpt->m_active->m_n_normal; i++) {
if ((cmd = mpt->m_active->m_slot[i]) != NULL) {
- if ((cmd->cmd_flags & CFLAG_CMDIOC) == 0) {
- cmd->cmd_active_timeout -=
- mptsas_scsi_watchdog_tick;
- if (cmd->cmd_active_timeout <= 0) {
+ if (cmd->cmd_active_expiration <= timestamp) {
+ if ((cmd->cmd_flags & CFLAG_CMDIOC) == 0) {
/*
* There seems to be a command stuck
* in the active slot. Drain throttle.
@@ -9418,14 +9416,9 @@ mptsas_watchsubr(mptsas_t *mpt)
mptsas_set_throttle(mpt,
cmd->cmd_tgt_addr,
DRAIN_THROTTLE);
- }
- }
- if ((cmd->cmd_flags & CFLAG_PASSTHRU) ||
- (cmd->cmd_flags & CFLAG_CONFIG) ||
- (cmd->cmd_flags & CFLAG_FW_DIAG)) {
- cmd->cmd_active_timeout -=
- mptsas_scsi_watchdog_tick;
- if (cmd->cmd_active_timeout <= 0) {
+ } else if (cmd->cmd_flags &
+ (CFLAG_PASSTHRU | CFLAG_CONFIG |
+ CFLAG_FW_DIAG)) {
/*
* passthrough command timeout
*/
@@ -9452,29 +9445,42 @@ mptsas_watchsubr(mptsas_t *mpt)
mptsas_restart_hba(mpt);
}
- if ((ptgt->m_t_ncmds > 0) &&
- (ptgt->m_timebase)) {
-
- if (ptgt->m_timebase <=
- mptsas_scsi_watchdog_tick) {
- ptgt->m_timebase +=
- mptsas_scsi_watchdog_tick;
- continue;
- }
+ cmd = TAILQ_LAST(&ptgt->m_active_cmdq, mptsas_active_cmdq);
+ if (cmd == NULL)
+ continue;
- ptgt->m_timeout -= mptsas_scsi_watchdog_tick;
+ if (cmd->cmd_active_expiration <= timestamp) {
+ /*
+ * Earliest command timeout expired. Drain throttle.
+ */
+ mptsas_set_throttle(mpt, ptgt, DRAIN_THROTTLE);
- if (ptgt->m_timeout < 0) {
- mptsas_cmd_timeout(mpt, ptgt->m_devhdl);
+ /*
+ * Check for remaining commands.
+ */
+ cmd = TAILQ_FIRST(&ptgt->m_active_cmdq);
+ if (cmd->cmd_active_expiration > timestamp) {
+ /*
+ * Wait for remaining commands to complete or
+ * time out.
+ */
+ NDBG23(("command timed out, pending drain"));
continue;
}
- if ((ptgt->m_timeout) <=
- mptsas_scsi_watchdog_tick) {
- NDBG23(("pending timeout"));
- mptsas_set_throttle(mpt, ptgt,
- DRAIN_THROTTLE);
- }
+ /*
+ * All command timeouts expired.
+ */
+ mptsas_log(mpt, CE_NOTE, "Timeout of %d seconds "
+ "expired with %d commands on target %d lun %d.",
+ cmd->cmd_pkt->pkt_time, ptgt->m_t_ncmds,
+ ptgt->m_devhdl, Lun(cmd));
+
+ mptsas_cmd_timeout(mpt, ptgt);
+ } else if (cmd->cmd_active_expiration <=
+ timestamp + (hrtime_t)mptsas_scsi_watchdog_tick * NANOSEC) {
+ NDBG23(("pending timeout"));
+ mptsas_set_throttle(mpt, ptgt, DRAIN_THROTTLE);
}
}
}
@@ -9483,16 +9489,28 @@ mptsas_watchsubr(mptsas_t *mpt)
* timeout recovery
*/
static void
-mptsas_cmd_timeout(mptsas_t *mpt, uint16_t devhdl)
+mptsas_cmd_timeout(mptsas_t *mpt, mptsas_target_t *ptgt)
{
+ uint16_t devhdl;
+ uint64_t sas_wwn;
+ uint8_t phy;
+ char wwn_str[MPTSAS_WWN_STRLEN];
+
+ devhdl = ptgt->m_devhdl;
+ sas_wwn = ptgt->m_addr.mta_wwn;
+ phy = ptgt->m_phynum;
+ if (sas_wwn == 0) {
+ (void) sprintf(wwn_str, "p%x", phy);
+ } else {
+ (void) sprintf(wwn_str, "w%016"PRIx64, sas_wwn);
+ }
NDBG29(("mptsas_cmd_timeout: target=%d", devhdl));
mptsas_log(mpt, CE_WARN, "Disconnected command timeout for "
- "Target %d", devhdl);
+ "target %d %s.", devhdl, wwn_str);
/*
- * If the current target is not the target passed in,
- * try to reset that target.
+ * Abort all outstanding commands on the device.
*/
NDBG29(("mptsas_cmd_timeout: device reset"));
if (mptsas_do_scsi_reset(mpt, devhdl) != TRUE) {
@@ -15268,6 +15286,7 @@ mptsas_tgt_alloc(mptsas_t *mpt, uint16_t devhdl, uint64_t wwid,
tmp_tgt->m_qfull_retry_interval =
drv_usectohz(QFULL_RETRY_INTERVAL * 1000);
tmp_tgt->m_t_throttle = MAX_THROTTLE;
+ TAILQ_INIT(&tmp_tgt->m_active_cmdq);
refhash_insert(mpt->m_targets, tmp_tgt);
diff --git a/usr/src/uts/common/sys/scsi/adapters/mpt_sas/mptsas_var.h b/usr/src/uts/common/sys/scsi/adapters/mpt_sas/mptsas_var.h
index 96b9b11464..4c5bd659eb 100644
--- a/usr/src/uts/common/sys/scsi/adapters/mpt_sas/mptsas_var.h
+++ b/usr/src/uts/common/sys/scsi/adapters/mpt_sas/mptsas_var.h
@@ -21,7 +21,7 @@
/*
* Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright 2012 Nexenta Systems, Inc. All rights reserved.
+ * Copyright 2014 Nexenta Systems, Inc. All rights reserved.
* Copyright (c) 2013, Joyent, Inc. All rights reserved.
*/
@@ -56,6 +56,7 @@
#define _SYS_SCSI_ADAPTERS_MPTVAR_H
#include <sys/byteorder.h>
+#include <sys/queue.h>
#include <sys/isa_defs.h>
#include <sys/sunmdi.h>
#include <sys/mdi_impldefs.h>
@@ -200,6 +201,9 @@ typedef struct mptsas_target_addr {
mptsas_phymask_t mta_phymask;
} mptsas_target_addr_t;
+TAILQ_HEAD(mptsas_active_cmdq, mptsas_cmd);
+typedef struct mptsas_active_cmdq mptsas_active_cmdq_t;
+
typedef struct mptsas_target {
mptsas_target_addr_t m_addr;
refhash_link_t m_link;
@@ -208,8 +212,7 @@ typedef struct mptsas_target {
uint32_t m_deviceinfo;
uint8_t m_phynum;
uint32_t m_dups;
- int32_t m_timeout;
- int32_t m_timebase;
+ mptsas_active_cmdq_t m_active_cmdq;
int32_t m_t_throttle;
int32_t m_t_ncmds;
int32_t m_reset_delay;
@@ -265,8 +268,9 @@ typedef struct mptsas_cmd {
int cmd_pkt_flags;
- /* timer for command in active slot */
- int cmd_active_timeout;
+ /* pending expiration time for command in active slot */
+ hrtime_t cmd_active_expiration;
+ TAILQ_ENTRY(mptsas_cmd) cmd_active_link;
struct scsi_pkt *cmd_pkt;
struct scsi_arq_status cmd_scb;
@@ -1169,7 +1173,7 @@ _NOTE(DATA_READABLE_WITHOUT_LOCK(mptsas::m_instance))
*/
#define DEFAULT_SCSI_OPTIONS SCSI_OPTIONS_DR
#define DEFAULT_TAG_AGE_LIMIT 2
-#define DEFAULT_WD_TICK 10
+#define DEFAULT_WD_TICK 1
/*
* invalid hostid.
diff --git a/usr/src/uts/common/sys/time.h b/usr/src/uts/common/sys/time.h
index 9fc4704860..eba6cb5277 100644
--- a/usr/src/uts/common/sys/time.h
+++ b/usr/src/uts/common/sys/time.h
@@ -234,7 +234,7 @@ struct itimerval32 {
#define SEC 1
#define MILLISEC 1000
#define MICROSEC 1000000
-#define NANOSEC 1000000000
+#define NANOSEC 1000000000LL
#define MSEC2NSEC(m) ((hrtime_t)(m) * (NANOSEC / MILLISEC))
#define NSEC2MSEC(n) ((n) / (NANOSEC / MILLISEC))