1 /*
   2  * CDDL HEADER START
   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 
  22 /*
  23  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
  24  * Use is subject to license terms.
  25  */
  26 
  27 
  28 #include <sys/types.h>
  29 #include <sys/conf.h>
  30 #include <sys/ddi.h>
  31 #include <sys/sunddi.h>
  32 #include <sys/ksynch.h>
  33 #include <sys/scsi/conf/autoconf.h>
  34 #include <sys/reboot.h>
  35 
  36 #include "ghd.h"
  37 
  38 /*
  39  * Local functions
  40  */
  41 
  42 static  gcmd_t  *ghd_timeout_get(ccc_t *cccp);
  43 static  int      ghd_timeout_loop(ccc_t *cccp);
  44 static  uint_t   ghd_timeout_softintr(caddr_t arg);
  45 static  void     ghd_timeout(void *arg);
  46 static  void     ghd_timeout_disable(tmr_t *tmrp);
  47 static  void     ghd_timeout_enable(tmr_t *tmrp);
  48 
  49 /*
  50  * Local data
  51  */
  52 long    ghd_HZ;
  53 static  kmutex_t tglobal_mutex;
  54 
  55 /* table of timeouts for abort processing steps */
  56 cmdstate_t ghd_timeout_table[GCMD_NSTATES];
  57 
  58 /* This table indirectly initializes the ghd_timeout_table */
  59 struct {
  60         int             valid;
  61         cmdstate_t      state;
  62         long            value;
  63 } ghd_time_inits[] = {
  64         { TRUE, GCMD_STATE_ABORTING_CMD, 3 },
  65         { TRUE, GCMD_STATE_ABORTING_DEV, 3 },
  66         { TRUE, GCMD_STATE_RESETTING_DEV, 5 },
  67         { TRUE, GCMD_STATE_RESETTING_BUS, 10 },
  68         { TRUE, GCMD_STATE_HUNG, 60},
  69         { FALSE, 0, 0 },        /* spare entry */
  70         { FALSE, 0, 0 },        /* spare entry */
  71         { FALSE, 0, 0 },        /* spare entry */
  72         { FALSE, 0, 0 },        /* spare entry */
  73         { FALSE, 0, 0 }         /* spare entry */
  74 };
  75 int     ghd_ntime_inits = sizeof (ghd_time_inits)
  76                                 / sizeof (ghd_time_inits[0]);
  77 
  78 /*
  79  * Locally-used macros
  80  */
  81 
  82 /*
  83  * Compare two gcmd_t's to see if they're for the same device (same gdev_t)
  84  */
  85 #define GCMD_SAME_DEV(gcmdp1, gcmdp2)           \
  86         (GCMDP2GDEVP(gcmdp1) == GCMDP2GDEVP(gcmdp2))
  87 
  88 /*
  89  * Compare two gcmd_t's to see if they're for the same bus (same HBA inst)
  90  */
  91 #define GCMD_SAME_BUS(gcmdp1, gcmdp2)           \
  92         (GCMDP2CCCP(gcmdp1) == GCMDP2CCCP(gcmdp2))
  93 
  94 
  95 /*
  96  * Update state of gcmdp (in one direction, increasing state number, only)
  97  */
  98 #define GCMD_UPDATE_STATE(gcmdp, newstate)              \
  99 {                                                       \
 100         if ((gcmdp)->cmd_state < (newstate)) {            \
 101                 ((gcmdp)->cmd_state = (newstate));   \
 102         }                                               \
 103 }
 104 
 105 #ifdef ___notyet___
 106 
 107 #include <sys/modctl.h>
 108 extern struct mod_ops mod_miscops;
 109 static struct modlmisc modlmisc = {
 110         &mod_miscops,       /* Type of module */
 111         "CCB Timeout Utility Routines"
 112 };
 113 static struct modlinkage modlinkage = {
 114         MODREV_1, (void *)&modlmisc, NULL
 115 };
 116 
 117 /*
 118  * If this is a loadable module then there's a single CCB timer configure
 119  * structure for all HBA drivers (rather than one per HBA driver).
 120  */
 121 static  tmr_t   tmr_conf;
 122 
 123 int
 124 _init()
 125 {
 126         int     err;
 127 
 128         ghd_timer_init(&tmr_conf, 0);
 129         return ((err = mod_install(&modlinkage)) != 0)
 130             ghd_timer_fini(&tmr_conf);
 131         return (err);
 132 }
 133 
 134 int
 135 _fini()
 136 {
 137         int     err;
 138 
 139         if ((err = mod_remove(&modlinkage)) == 0)
 140                 ghd_timer_fini(&tmr_conf);
 141         return (err);
 142 }
 143 
 144 int
 145 _info(struct modinfo *modinfop)
 146 {
 147         return (mod_info(&modlinkage, modinfop));
 148 }
 149 
 150 #endif /* ___notyet___ */
 151 
 152 
 153 
 154 /*
 155  *
 156  * ghd_timeout_loop()
 157  *
 158  *      Check the CCB timer value for every active CCB for this
 159  * HBA driver instance.
 160  *
 161  *      This function is called both by the ghd_timeout() interrupt
 162  * handler when called via the timer callout, and by ghd_timer_poll()
 163  * while procesing "polled" (FLAG_NOINTR) requests.
 164  *
 165  *      The ccc_activel_mutex is held while a CCB list is being scanned.
 166  * This prevents the HBA driver's transport or interrupt functions
 167  * from changing the active CCB list. But we wake up very infrequently
 168  * and do as little as possible so it shouldn't affect performance.
 169  *
 170  */
 171 
 172 static int
 173 ghd_timeout_loop(ccc_t *cccp)
 174 {
 175         int      got_any = FALSE;
 176         gcmd_t  *gcmdp;
 177         ulong_t  lbolt;
 178 
 179         mutex_enter(&cccp->ccc_activel_mutex);
 180         lbolt = ddi_get_lbolt();
 181         gcmdp = (gcmd_t *)L2_next(&cccp->ccc_activel);
 182         while (gcmdp) {
 183                 /*
 184                  * check to see if this one has timed out
 185                  */
 186                 if ((gcmdp->cmd_timeout > 0) &&
 187                     (lbolt - gcmdp->cmd_start_time >= gcmdp->cmd_timeout)) {
 188                         got_any = TRUE;
 189                 }
 190                 gcmdp = (gcmd_t *)L2_next(&gcmdp->cmd_timer_link);
 191         }
 192         mutex_exit(&cccp->ccc_activel_mutex);
 193         return (got_any);
 194 }
 195 
 196 /*
 197  *
 198  * ghd_timeout()
 199  *
 200  *      Called every t_ticks ticks to scan the CCB timer lists
 201  *
 202  *      The t_mutex mutex is held the entire time this routine is active.
 203  *      It protects the list of ccc_t's.
 204  *
 205  *      The list of cmd_t's is protected by the ccc_activel_mutex mutex
 206  *      in the ghd_timeout_loop() routine.
 207  *
 208  *      We also check to see if the waitq is frozen, and if so,
 209  *      adjust our timeout to call back sooner if necessary (to
 210  *      unfreeze the waitq as soon as possible).
 211  *
 212  *
 213  *      +------------+
 214  *      |   tmr_t    |----+
 215  *      +------------+    |
 216  *                        |
 217  *                        V
 218  *                        +---------+
 219  *                        |  ccc_t  |----+
 220  *                        +---------+    |
 221  *                        |              V
 222  *                        |              +--------+   +--------+
 223  *                        |              | gcmd_t |-->| gcmd_t |--> ...
 224  *                        |              +--------+   +--------+
 225  *                        V
 226  *                        +---------+
 227  *                        |  ccc_t  |----+
 228  *                        +---------+    |
 229  *                        |              V
 230  *                        |              +--------+
 231  *                        |              | gcmd_t |
 232  *                        V              +--------+
 233  *                        ...
 234  *
 235  *
 236  *
 237  */
 238 
 239 static void
 240 ghd_timeout(void *arg)
 241 {
 242         tmr_t   *tmrp = (tmr_t *)arg;
 243         ccc_t   *cccp;
 244         clock_t ufdelay_curr;
 245         clock_t lbolt, delay_in_hz;
 246         clock_t resched = (clock_t)0x7FFFFFFF;
 247 
 248         /*
 249          * Each HBA driver instance has a separate CCB timer list.  Skip
 250          * timeout processing if there are no more active timeout lists
 251          * to process.  (There are no lists only if there are no attached
 252          * HBA instances; the list still exists if there are no outstanding
 253          * active commands.)
 254          */
 255         mutex_enter(&tmrp->t_mutex);
 256         if ((cccp = tmrp->t_ccc_listp) == NULL) {
 257                 mutex_exit(&tmrp->t_mutex);
 258                 return;
 259         }
 260 
 261         lbolt = ddi_get_lbolt();
 262 
 263         do {
 264                 /*
 265                  * If any active CCBs on this HBA have timed out
 266                  * then kick off the HBA driver's softintr
 267                  * handler to do the timeout processing
 268                  */
 269                 if (ghd_timeout_loop(cccp)) {
 270                         cccp->ccc_timeout_pending = 1;
 271                         ddi_trigger_softintr(cccp->ccc_soft_id);
 272                 }
 273 
 274                 /* Record closest unfreeze time for use in next timeout */
 275 
 276                 mutex_enter(&cccp->ccc_waitq_mutex);
 277                 if (cccp->ccc_waitq_frozen) {
 278 
 279                         delay_in_hz =
 280                             drv_usectohz(cccp->ccc_waitq_freezedelay * 1000);
 281                         ufdelay_curr = delay_in_hz -
 282                             (lbolt - cccp->ccc_waitq_freezetime);
 283 
 284                         if (ufdelay_curr < resched)
 285                                 resched = ufdelay_curr;
 286 
 287                         /* frozen; trigger softintr to maybe unfreeze */
 288                         ddi_trigger_softintr(cccp->ccc_soft_id);
 289                 }
 290                 mutex_exit(&cccp->ccc_waitq_mutex);
 291 
 292         } while ((cccp = cccp->ccc_nextp) != NULL);
 293 
 294         /* don't allow any unfreeze delays to increase the timeout delay */
 295         if (resched > tmrp->t_ticks)
 296                 resched = tmrp->t_ticks;
 297 
 298         /* re-establish the timeout callback */
 299         tmrp->t_timeout_id = timeout(ghd_timeout, (void *)tmrp, resched);
 300 
 301         mutex_exit(&tmrp->t_mutex);
 302 }
 303 
 304 
 305 /*
 306  *
 307  * ghd_timer_newstate()
 308  *
 309  *      The HBA mutex is held by my caller.
 310  *
 311  */
 312 
 313 void
 314 ghd_timer_newstate(ccc_t *cccp, gcmd_t *gcmdp, gtgt_t *gtgtp,
 315     gact_t action, int calltype)
 316 {
 317         gact_t  next_action;
 318         cmdstate_t next_state;
 319         char    *msgp;
 320         long    new_timeout;
 321         int     (*func)(void *, gcmd_t *, gtgt_t *, gact_t, int);
 322         void    *hba_handle;
 323         gcmd_t  gsav;
 324         int     gsav_used = 0;
 325         gcmd_t  *gcmdp_scan;
 326 
 327         ASSERT(mutex_owned(&cccp->ccc_hba_mutex));
 328 
 329 #ifdef  DEBUG
 330         /* it shouldn't be on the timer active list */
 331         if (gcmdp != NULL) {
 332                 L2el_t  *lp = &gcmdp->cmd_timer_link;
 333                 ASSERT(lp->l2_nextp == lp);
 334                 ASSERT(lp->l2_prevp == lp);
 335         }
 336 #endif
 337 
 338         func = cccp->ccc_timeout_func;
 339         hba_handle = cccp->ccc_hba_handle;
 340 
 341         for (;;) {
 342                 switch (action) {
 343                 case GACTION_EARLY_ABORT:
 344                         /* done before it started */
 345                         ASSERT(gcmdp != NULL);
 346                         msgp = "early abort";
 347                         next_state = GCMD_STATE_DONEQ;
 348                         next_action = GACTION_ABORT_CMD;
 349                         break;
 350 
 351                 case GACTION_EARLY_TIMEOUT:
 352                         /* done before it started */
 353                         ASSERT(gcmdp != NULL);
 354                         msgp = "early timeout";
 355                         next_state = GCMD_STATE_DONEQ;
 356                         next_action = GACTION_ABORT_CMD;
 357                         break;
 358 
 359                 case GACTION_ABORT_CMD:
 360                         msgp = "abort request";
 361                         ASSERT(gcmdp != NULL);
 362                         next_state = GCMD_STATE_ABORTING_CMD;
 363                         next_action = GACTION_ABORT_DEV;
 364                         break;
 365 
 366                 case GACTION_ABORT_DEV:
 367                         msgp = "abort device";
 368                         next_state = GCMD_STATE_ABORTING_DEV;
 369                         next_action = GACTION_RESET_TARGET;
 370                         break;
 371 
 372                 case GACTION_RESET_TARGET:
 373                         msgp = "reset target";
 374                         next_state = GCMD_STATE_RESETTING_DEV;
 375                         next_action = GACTION_RESET_BUS;
 376                         break;
 377 
 378                 case GACTION_RESET_BUS:
 379                         msgp = "reset bus";
 380                         next_state = GCMD_STATE_RESETTING_BUS;
 381                         next_action = GACTION_INCOMPLETE;
 382                         break;
 383 
 384                 case GACTION_INCOMPLETE:
 385                 default:
 386                         /* be verbose about HBA resets */
 387                         GDBG_ERROR(("?ghd_timer_newstate: HBA reset failed "
 388                             "hba 0x%p gcmdp 0x%p gtgtp 0x%p\n",
 389                             (void *)hba_handle, (void *)gcmdp, (void *)gtgtp));
 390                         /*
 391                          * When all else fails, punt.
 392                          *
 393                          * We're in big trouble if we get to this point.
 394                          * Maybe we should try to re-initialize the HBA.
 395                          */
 396                         msgp = "HBA reset";
 397                         next_state = GCMD_STATE_HUNG;
 398                         next_action = GACTION_INCOMPLETE;
 399                         break;
 400                 }
 401 
 402                 /*
 403                  * I want to see target requests only if verbose, but
 404                  * scsi_log() only prints the device pathname if level
 405                  * is CE_WARN or CE_PANIC...so I guess we can't use
 406                  * scsi_log for TGTREQ messages, or they must come to
 407                  * the console.  How silly.  Looking for "verbose boot"
 408                  * is non-DDI-compliant, but let's do it anyway.
 409                  */
 410 
 411                 if (calltype == GHD_TGTREQ) {
 412                         if ((boothowto & RB_VERBOSE)) {
 413                                 scsi_log(cccp->ccc_hba_dip, cccp->ccc_label,
 414                                     CE_WARN,
 415                                     "target request: %s, target=%d lun=%d",
 416                                     msgp, gtgtp->gt_target, gtgtp->gt_lun);
 417                         }
 418                 } else {
 419                         scsi_log(cccp->ccc_hba_dip, cccp->ccc_label, CE_WARN,
 420                             "timeout: %s, target=%d lun=%d", msgp,
 421                             gtgtp->gt_target, gtgtp->gt_lun);
 422                 }
 423 
 424                 /*
 425                  * Before firing off the HBA action, restart the timer
 426                  * using the timeout value from ghd_timeout_table[].
 427                  *
 428                  * The table entries should never restart the timer
 429                  * for the GHD_STATE_IDLE and GHD_STATE_DONEQ states.
 430                  *
 431                  */
 432                 if (gcmdp) {
 433                         gcmdp->cmd_state = next_state;
 434                         new_timeout = ghd_timeout_table[gcmdp->cmd_state];
 435                         if (new_timeout != 0)
 436                                 ghd_timer_start(cccp, gcmdp, new_timeout);
 437 
 438                         /* save a copy in case action function frees it */
 439                         gsav = *gcmdp;
 440                         gsav_used = 1;
 441                 }
 442 
 443                 if (action == GACTION_RESET_BUS && cccp->ccc_waitq_frozen) {
 444                         GDBG_WARN(("avoiding bus reset while waitq frozen\n"));
 445                         break;
 446                 }
 447 
 448                 /* invoke the HBA's action function */
 449                 if ((*func)(hba_handle, gcmdp, gtgtp, action, calltype)) {
 450                         /* if it took wait for an interrupt or timeout */
 451                         break;
 452                 }
 453                 /*
 454                  * if the HBA reset fails leave the retry
 455                  * timer running and just exit.
 456                  */
 457                 if (action == GACTION_INCOMPLETE)
 458                         return;
 459 
 460                 /* all other failures cause transition to next action */
 461                 if (gcmdp != NULL && new_timeout != 0) {
 462                         /*
 463                          * But stop the old timer prior to
 464                          * restarting a new timer because each step may
 465                          * have a different timeout value.
 466                          */
 467                         GHD_TIMER_STOP(cccp, gcmdp);
 468                 }
 469                 action = next_action;
 470         }
 471 
 472         /*
 473          * HBA action function is done with gsav (if used)
 474          * or gtgtp/cccp (if gsav not used).  We need to mark other
 475          * outstanding requests if they were affected by this action
 476          * (say, a device reset which also cancels all outstanding
 477          * requests on this device) to prevent multiple timeouts/HBA
 478          * actions for the same device or bus condition.  Scan the timer
 479          * list (all active requests) and update states as necessary.
 480          * Hold the activel_mutex while scanning the active list.  Check
 481          * for either same dev/bus as gsav (if used) or for same
 482          * dev/bus as gtgtp or cccp (if gsav is not used).
 483          */
 484 
 485         mutex_enter(&cccp->ccc_activel_mutex);
 486 
 487         for (gcmdp_scan = (gcmd_t *)L2_next(&cccp->ccc_activel);
 488             gcmdp_scan != NULL;
 489             gcmdp_scan = (gcmd_t *)L2_next(&gcmdp_scan->cmd_timer_link)) {
 490 
 491                 /* skip idle or waitq commands */
 492                 if (gcmdp_scan->cmd_state <= GCMD_STATE_WAITQ)
 493                         continue;
 494 
 495                 switch (action) {
 496 
 497                 case GACTION_ABORT_DEV:
 498                         if ((gsav_used && GCMD_SAME_DEV(&gsav, gcmdp_scan)) ||
 499                             (GCMDP2GDEVP(gcmdp_scan) == GTGTP2GDEVP(gtgtp))) {
 500                                 GCMD_UPDATE_STATE(gcmdp_scan,
 501                                     GCMD_STATE_ABORTING_DEV);
 502                         }
 503                         break;
 504 
 505                 case GACTION_RESET_TARGET:
 506                         if ((gsav_used && GCMD_SAME_DEV(&gsav, gcmdp_scan)) ||
 507                             (GCMDP2GDEVP(gcmdp_scan) == GTGTP2GDEVP(gtgtp))) {
 508                                 GCMD_UPDATE_STATE(gcmdp_scan,
 509                                     GCMD_STATE_RESETTING_DEV);
 510                         }
 511                         break;
 512 
 513                 case GACTION_RESET_BUS:
 514                         if ((gsav_used && GCMD_SAME_BUS(&gsav, gcmdp_scan)) ||
 515                             (GCMDP2CCCP(gcmdp_scan) == cccp)) {
 516                                 GCMD_UPDATE_STATE(gcmdp_scan,
 517                                     GCMD_STATE_RESETTING_BUS);
 518                         }
 519                         break;
 520                 default:
 521                         break;
 522                 }
 523         }
 524 
 525         mutex_exit(&cccp->ccc_activel_mutex);
 526 }
 527 
 528 
 529 /*
 530  *
 531  * ghd_timeout_softintr()
 532  *
 533  *      This interrupt is scheduled if a particular HBA instance's
 534  *      CCB timer list has a timed out CCB, or if the waitq is in a
 535  *      frozen state.
 536  *
 537  *      Find the timed out CCB and then call the HBA driver's timeout
 538  *      function.
 539  *
 540  *      In order to avoid race conditions all processing must be done
 541  *      while holding the HBA instance's mutex. If the mutex wasn't
 542  *      held the HBA driver's hardware interrupt routine could be
 543  *      triggered and it might try to remove a CCB from the list at
 544  *      same time as were trying to abort it.
 545  *
 546  *      For frozen-waitq processing, just call ghd_waitq_process...
 547  *      it takes care of the time calculations.
 548  *
 549  */
 550 
 551 static uint_t
 552 ghd_timeout_softintr(caddr_t arg)
 553 {
 554         ccc_t   *cccp = (ccc_t *)arg;
 555 
 556         if (cccp->ccc_timeout_pending) {
 557 
 558                 /* grab this HBA instance's mutex */
 559                 mutex_enter(&cccp->ccc_hba_mutex);
 560 
 561                 /*
 562                  * The claim is we could reset "pending" outside the mutex, but
 563                  * since we have to acquire the mutex anyway, it doesn't hurt
 564                  */
 565                 cccp->ccc_timeout_pending = 0;
 566 
 567                 /* timeout each expired CCB */
 568                 ghd_timer_poll(cccp, GHD_TIMER_POLL_ALL);
 569 
 570                 mutex_enter(&cccp->ccc_waitq_mutex);
 571                 ghd_waitq_process_and_mutex_exit(cccp);
 572 
 573         } else if (cccp->ccc_waitq_frozen) {
 574                 mutex_enter(&cccp->ccc_hba_mutex);
 575                 mutex_enter(&cccp->ccc_waitq_mutex);
 576                 ghd_waitq_process_and_mutex_exit(cccp);
 577         }
 578 
 579         return (DDI_INTR_UNCLAIMED);
 580 }
 581 
 582 
 583 /*
 584  * ghd_timer_poll()
 585  *
 586  * This function steps a packet to the next action in the recovery
 587  * procedure.
 588  *
 589  * The caller must be  already holding the HBA mutex and take care of
 590  * running the pkt completion functions.
 591  *
 592  */
 593 
 594 void
 595 ghd_timer_poll(ccc_t *cccp, gtimer_poll_t calltype)
 596 {
 597         gcmd_t  *gcmdp;
 598         gact_t   action;
 599 
 600         ASSERT(mutex_owned(&cccp->ccc_hba_mutex));
 601 
 602         /* abort each expired CCB */
 603         while (gcmdp = ghd_timeout_get(cccp)) {
 604 
 605                 GDBG_INTR(("?ghd_timer_poll: cccp=0x%p gcmdp=0x%p\n",
 606                     (void *)cccp, (void *)gcmdp));
 607 
 608                 switch (gcmdp->cmd_state) {
 609                 case GCMD_STATE_IDLE:
 610                 case GCMD_STATE_DONEQ:
 611                 default:
 612                         /* not supposed to happen */
 613                         GDBG_ERROR(("ghd_timer_poll: invalid state %d\n",
 614                             gcmdp->cmd_state));
 615                         return;
 616 
 617                 case GCMD_STATE_WAITQ:
 618                         action = GACTION_EARLY_TIMEOUT;
 619                         break;
 620 
 621                 case GCMD_STATE_ACTIVE:
 622                         action = GACTION_ABORT_CMD;
 623                         break;
 624 
 625                 case GCMD_STATE_ABORTING_CMD:
 626                         action = GACTION_ABORT_DEV;
 627                         break;
 628 
 629                 case GCMD_STATE_ABORTING_DEV:
 630                         action = GACTION_RESET_TARGET;
 631                         break;
 632 
 633                 case GCMD_STATE_RESETTING_DEV:
 634                         action = GACTION_RESET_BUS;
 635                         break;
 636 
 637                 case GCMD_STATE_RESETTING_BUS:
 638                         action = GACTION_INCOMPLETE;
 639                         break;
 640 
 641                 case GCMD_STATE_HUNG:
 642                         action = GACTION_INCOMPLETE;
 643                         break;
 644                 }
 645 
 646                 ghd_timer_newstate(cccp, gcmdp, gcmdp->cmd_gtgtp, action,
 647                     GHD_TIMEOUT);
 648 
 649                 /* return after processing first cmd if requested */
 650 
 651                 if (calltype == GHD_TIMER_POLL_ONE)
 652                         return;
 653         }
 654 }
 655 
 656 
 657 
 658 
 659 /*
 660  *
 661  * ghd_timeout_get()
 662  *
 663  *      Remove the first expired CCB from a particular timer list.
 664  *
 665  */
 666 
 667 static gcmd_t *
 668 ghd_timeout_get(ccc_t *cccp)
 669 {
 670         gcmd_t  *gcmdp;
 671         ulong_t lbolt;
 672 
 673         ASSERT(mutex_owned(&cccp->ccc_hba_mutex));
 674 
 675         mutex_enter(&cccp->ccc_activel_mutex);
 676         lbolt = ddi_get_lbolt();
 677         gcmdp = (gcmd_t *)L2_next(&cccp->ccc_activel);
 678         while (gcmdp != NULL) {
 679                 if ((gcmdp->cmd_timeout > 0) &&
 680                     (lbolt - gcmdp->cmd_start_time >= gcmdp->cmd_timeout))
 681                         goto expired;
 682                 gcmdp = (gcmd_t *)L2_next(&gcmdp->cmd_timer_link);
 683         }
 684         mutex_exit(&cccp->ccc_activel_mutex);
 685         return (NULL);
 686 
 687 expired:
 688         /* unlink if from the CCB timer list */
 689         L2_delete(&gcmdp->cmd_timer_link);
 690         mutex_exit(&cccp->ccc_activel_mutex);
 691         return (gcmdp);
 692 }
 693 
 694 
 695 /*
 696  *
 697  * ghd_timeout_enable()
 698  *
 699  *      Only start a single timeout callback for each HBA driver
 700  *      regardless of the number of boards it supports.
 701  *
 702  */
 703 
 704 static void
 705 ghd_timeout_enable(tmr_t *tmrp)
 706 {
 707         mutex_enter(&tglobal_mutex);
 708         if (tmrp->t_refs++ == 0)  {
 709                 /* establish the timeout callback */
 710                 tmrp->t_timeout_id = timeout(ghd_timeout, (void *)tmrp,
 711                     tmrp->t_ticks);
 712         }
 713         mutex_exit(&tglobal_mutex);
 714 }
 715 
 716 static void
 717 ghd_timeout_disable(tmr_t *tmrp)
 718 {
 719         ASSERT(tmrp != NULL);
 720 
 721         mutex_enter(&tglobal_mutex);
 722         if (tmrp->t_refs-- <= 1) {
 723                 (void) untimeout(tmrp->t_timeout_id);
 724         }
 725         mutex_exit(&tglobal_mutex);
 726 }
 727 
 728 /* ************************************************************************ */
 729 
 730         /* these are the externally callable routines */
 731 
 732 
 733 void
 734 ghd_timer_init(tmr_t *tmrp, long ticks)
 735 {
 736         int     indx;
 737 
 738         mutex_init(&tglobal_mutex, NULL, MUTEX_DRIVER, NULL);
 739         mutex_init(&tmrp->t_mutex, NULL, MUTEX_DRIVER, NULL);
 740 
 741         /*
 742          * determine default timeout value
 743          */
 744         ghd_HZ = drv_sectohz(1);
 745         if (ticks == 0)
 746                 ticks = scsi_watchdog_tick * ghd_HZ;
 747         tmrp->t_ticks = ticks;
 748 
 749 
 750         /*
 751          * Initialize the table of abort timer values using an
 752          * indirect lookup table so that this code isn't dependant
 753          * on the cmdstate_t enum values or order.
 754          */
 755         for (indx = 0; indx < ghd_ntime_inits; indx++) {
 756                 int     state;
 757                 ulong_t value;
 758 
 759                 if (!ghd_time_inits[indx].valid)
 760                         continue;
 761                 state = ghd_time_inits[indx].state;
 762                 value = ghd_time_inits[indx].value;
 763                 ghd_timeout_table[state] = (cmdstate_t)value;
 764         }
 765 }
 766 
 767 void
 768 ghd_timer_fini(tmr_t *tmrp)
 769 {
 770         mutex_destroy(&tmrp->t_mutex);
 771         mutex_destroy(&tglobal_mutex);
 772 }
 773 
 774 int
 775 ghd_timer_attach(ccc_t *cccp, tmr_t *tmrp,
 776     int (*timeout_func)(void *, gcmd_t *, gtgt_t *, gact_t, int))
 777 {
 778         ddi_iblock_cookie_t iblock;
 779 
 780         if (ddi_add_softintr(cccp->ccc_hba_dip, DDI_SOFTINT_LOW,
 781             &cccp->ccc_soft_id, &iblock, NULL,
 782             ghd_timeout_softintr, (caddr_t)cccp) != DDI_SUCCESS) {
 783                 GDBG_ERROR((
 784                     "ghd_timer_attach: add softintr failed cccp 0x%p\n",
 785                     (void *)cccp));
 786                 return (FALSE);
 787         }
 788 
 789         /* init the per HBA-instance control fields */
 790         mutex_init(&cccp->ccc_activel_mutex, NULL, MUTEX_DRIVER, iblock);
 791         L2_INIT(&cccp->ccc_activel);
 792         cccp->ccc_timeout_func = timeout_func;
 793 
 794         /* stick this HBA's control structure on the master list */
 795         mutex_enter(&tmrp->t_mutex);
 796 
 797         cccp->ccc_nextp = tmrp->t_ccc_listp;
 798         tmrp->t_ccc_listp = cccp;
 799         cccp->ccc_tmrp = tmrp;
 800         mutex_exit(&tmrp->t_mutex);
 801 
 802         /*
 803          * The enable and disable routines use a separate mutex than
 804          * t_mutex which is used by the timeout callback function.
 805          * This is to avoid a deadlock when calling untimeout() from
 806          * the disable routine.
 807          */
 808         ghd_timeout_enable(tmrp);
 809 
 810         return (TRUE);
 811 }
 812 
 813 
 814 /*
 815  *
 816  * ghd_timer_detach()
 817  *
 818  *      clean up for a detaching HBA instance
 819  *
 820  */
 821 
 822 void
 823 ghd_timer_detach(ccc_t *cccp)
 824 {
 825         tmr_t   *tmrp = cccp->ccc_tmrp;
 826         ccc_t   **prevpp;
 827 
 828         /* make certain the CCB list is empty */
 829         ASSERT(cccp->ccc_activel.l2_nextp == &cccp->ccc_activel);
 830         ASSERT(cccp->ccc_activel.l2_nextp == cccp->ccc_activel.l2_prevp);
 831 
 832         mutex_enter(&tmrp->t_mutex);
 833 
 834         prevpp = &tmrp->t_ccc_listp;
 835         ASSERT(*prevpp != NULL);
 836 
 837         /* run down the linked list to find the entry that preceeds this one */
 838         do {
 839                 if (*prevpp == cccp)
 840                         goto remove_it;
 841                 prevpp = &(*prevpp)->ccc_nextp;
 842         } while (*prevpp != NULL);
 843 
 844         /* fell off the end of the list */
 845         GDBG_ERROR(("ghd_timer_detach: corrupt list, cccp=0x%p\n",
 846             (void *)cccp));
 847 
 848 remove_it:
 849         *prevpp = cccp->ccc_nextp;
 850         mutex_exit(&tmrp->t_mutex);
 851         mutex_destroy(&cccp->ccc_activel_mutex);
 852 
 853         ddi_remove_softintr(cccp->ccc_soft_id);
 854 
 855         ghd_timeout_disable(tmrp);
 856 }
 857 
 858 /*
 859  *
 860  * ghd_timer_start()
 861  *
 862  *      Add a CCB to the CCB timer list.
 863  */
 864 
 865 void
 866 ghd_timer_start(ccc_t *cccp, gcmd_t *gcmdp, long cmd_timeout)
 867 {
 868         ulong_t lbolt;
 869 
 870         mutex_enter(&cccp->ccc_activel_mutex);
 871         lbolt = ddi_get_lbolt();
 872 
 873         /* initialize this CCB's timer */
 874         gcmdp->cmd_start_time = lbolt;
 875         gcmdp->cmd_timeout = (cmd_timeout * ghd_HZ);
 876 
 877         /* add it to the list */
 878         L2_add(&cccp->ccc_activel, &gcmdp->cmd_timer_link, gcmdp);
 879         mutex_exit(&cccp->ccc_activel_mutex);
 880 }
 881 
 882 
 883 /*
 884  *
 885  * ghd_timer_stop()
 886  *
 887  *      Remove a completed CCB from the CCB timer list.
 888  *
 889  *      See the GHD_TIMER_STOP_INLINE() macro in ghd.h for
 890  *      the actual code.
 891  */
 892 
 893 void
 894 ghd_timer_stop(ccc_t *cccp, gcmd_t *gcmdp)
 895 {
 896         GHD_TIMER_STOP_INLINE(cccp, gcmdp);
 897 }