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  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  23  * Use is subject to license terms.
  24  */
  25 
  26 /*
  27  * generic scsi device watch
  28  */
  29 
  30 #if DEBUG || lint
  31 #define SWDEBUG
  32 #endif
  33 
  34 /*
  35  * debug goodies
  36  */
  37 #ifdef SWDEBUG
  38 static int swdebug = 0;
  39 #define DEBUGGING       ((scsi_options & SCSI_DEBUG_TGT) && sddebug > 1)
  40 #define SW_DEBUG        if (swdebug == 1) scsi_log
  41 #define SW_DEBUG2       if (swdebug > 1) scsi_log
  42 #else   /* SWDEBUG */
  43 #define swdebug         (0)
  44 #define DEBUGGING       (0)
  45 #define SW_DEBUG        if (0) scsi_log
  46 #define SW_DEBUG2       if (0) scsi_log
  47 #endif
  48 
  49 
  50 
  51 /*
  52  * Includes, Declarations and Local Data
  53  */
  54 
  55 #include <sys/note.h>
  56 #include <sys/scsi/scsi.h>
  57 #include <sys/var.h>
  58 #include <sys/proc.h>
  59 #include <sys/thread.h>
  60 #include <sys/callb.h>
  61 
  62 /*
  63  * macro for filling in lun value for scsi-1 support
  64  */
  65 #define FILL_SCSI1_LUN(devp, pkt) \
  66         if ((devp->sd_address.a_lun > 0) && \
  67             (devp->sd_inq->inq_ansi == 0x1)) { \
  68                 ((union scsi_cdb *)(pkt)->pkt_cdbp)->scc_lun = \
  69                     devp->sd_address.a_lun; \
  70         }
  71 
  72 char *sw_label = "scsi-watch";
  73 
  74 static int scsi_watch_io_time = SCSI_WATCH_IO_TIME;
  75 
  76 /*
  77  * all info resides in the scsi watch structure
  78  *
  79  * the monitoring is performed by one separate thread which works
  80  * from a linked list of scsi_watch_request packets
  81  */
  82 static struct scsi_watch {
  83         kthread_t               *sw_thread;     /* the watch thread     */
  84         kmutex_t                sw_mutex;       /* mutex protecting list */
  85                                                 /* and this structure */
  86         kcondvar_t              sw_cv;          /* cv for waking up thread */
  87         struct scsi_watch_request *sw_head;     /* head of linked list  */
  88                                                 /* of request structures */
  89         uchar_t                 sw_state;       /* for suspend-resume */
  90         uchar_t                 sw_flags;       /* to start at head of list */
  91                                                 /* for watch thread */
  92         struct scsi_watch_request *swr_current; /* the command waiting to be */
  93                                                 /* processed by the watch */
  94                                                 /* thread which is being */
  95                                                 /* blocked */
  96 } sw;
  97 
  98 #if !defined(lint)
  99 _NOTE(MUTEX_PROTECTS_DATA(scsi_watch::sw_mutex, scsi_watch))
 100 #endif
 101 
 102 /*
 103  * Values for sw_state
 104  */
 105 #define SW_RUNNING              0
 106 #define SW_SUSPEND_REQUESTED    1
 107 #define SW_SUSPENDED            2
 108 
 109 /*
 110  * values for sw_flags
 111  */
 112 #define SW_START_HEAD           0x1
 113 
 114 struct scsi_watch_request {
 115         struct scsi_watch_request *swr_next;    /* linked request list  */
 116         struct scsi_watch_request *swr_prev;
 117         clock_t                 swr_interval;   /* interval between TURs */
 118         clock_t                 swr_timeout;    /* count down           */
 119         uchar_t                 swr_busy;       /* TUR in progress      */
 120         uchar_t                 swr_what;       /* watch or stop        */
 121         uchar_t                 swr_sense_length; /* required sense length */
 122         struct scsi_pkt         *swr_pkt;       /* TUR pkt itself       */
 123         struct scsi_pkt         *swr_rqpkt;     /* request sense pkt    */
 124         struct buf              *swr_rqbp;      /* bp for request sense data */
 125         struct buf              *swr_mmcbp;     /* bp for MMC command data */
 126         int                     (*swr_callback)(); /* callback to driver */
 127         caddr_t                 swr_callback_arg;
 128         kcondvar_t              swr_terminate_cv; /* cv to wait on to cleanup */
 129                                                 /* request synchronously */
 130         int                     swr_ref;        /*  refer count to the swr */
 131         uchar_t                 suspend_destroy; /* flag for free later */
 132 };
 133 
 134 /*
 135  * values for swr flags
 136  */
 137 #define SUSPEND_DESTROY         1
 138 
 139 #if !defined(lint)
 140 _NOTE(SCHEME_PROTECTS_DATA("unshared data", scsi_watch_request))
 141 #endif
 142 
 143 /*
 144  * values for sw_what
 145  */
 146 #define SWR_WATCH               0       /* device watch */
 147 #define SWR_STOP                1       /* stop monitoring and destroy swr */
 148 #define SWR_SUSPEND_REQUESTED   2       /* req. pending suspend */
 149 #define SWR_SUSPENDED           3       /* req. is suspended */
 150 
 151 static opaque_t scsi_watch_request_submit_impl(struct scsi_device *devp,
 152     int interval, int sense_length, int (*callback)(), caddr_t cb_arg,
 153     boolean_t mmc);
 154 static void scsi_watch_request_destroy(struct scsi_watch_request *swr);
 155 static void scsi_watch_thread(void);
 156 static void scsi_watch_request_intr(struct scsi_pkt *pkt);
 157 
 158 /*
 159  * setup, called from _init(), the thread is created when we need it
 160  * and exits when there is nothing to do anymore and everything has been
 161  * cleaned up (ie. resources deallocated)
 162  */
 163 void
 164 scsi_watch_init()
 165 {
 166 /* NO OTHER THREADS ARE RUNNING */
 167         mutex_init(&sw.sw_mutex, NULL, MUTEX_DRIVER, NULL);
 168         cv_init(&sw.sw_cv, NULL, CV_DRIVER, NULL);
 169         sw.sw_state = SW_RUNNING;
 170         sw.sw_flags = 0;
 171         sw.swr_current = NULL;
 172 }
 173 
 174 /*
 175  * cleaning up, called from _fini()
 176  */
 177 void
 178 scsi_watch_fini()
 179 {
 180 /* NO OTHER THREADS ARE RUNNING */
 181         /*
 182          * hope and pray that the thread has exited
 183          */
 184         ASSERT(sw.sw_thread == 0);
 185         mutex_destroy(&sw.sw_mutex);
 186         cv_destroy(&sw.sw_cv);
 187 }
 188 
 189 /*
 190  * allocate an swr (scsi watch request structure) and initialize pkts
 191  */
 192 #define ROUTE           &devp->sd_address
 193 
 194 opaque_t
 195 scsi_watch_request_submit(
 196         struct scsi_device      *devp,
 197         int                     interval,
 198         int                     sense_length,
 199         int                     (*callback)(),  /* callback function */
 200         caddr_t                 cb_arg)         /* device number */
 201 {
 202         return (scsi_watch_request_submit_impl(devp, interval, sense_length,
 203             callback, cb_arg, B_FALSE));
 204 }
 205 
 206 opaque_t
 207 scsi_mmc_watch_request_submit(
 208         struct scsi_device      *devp,
 209         int                     interval,
 210         int                     sense_length,
 211         int                     (*callback)(),  /* callback function */
 212         caddr_t                 cb_arg)         /* device number */
 213 {
 214         return (scsi_watch_request_submit_impl(devp, interval, sense_length,
 215             callback, cb_arg, B_TRUE));
 216 }
 217 
 218 static opaque_t
 219 scsi_watch_request_submit_impl(
 220         struct scsi_device      *devp,
 221         int                     interval,
 222         int                     sense_length,
 223         int                     (*callback)(),  /* callback function */
 224         caddr_t                 cb_arg,         /* device number */
 225         boolean_t               mmc)
 226 {
 227         register struct scsi_watch_request      *swr = NULL;
 228         register struct scsi_watch_request      *sswr, *p;
 229         struct buf                              *bp = NULL;
 230         struct buf                              *mmcbp = NULL;
 231         struct scsi_pkt                         *rqpkt = NULL;
 232         struct scsi_pkt                         *pkt = NULL;
 233         uchar_t                                 dtype;
 234 
 235         SW_DEBUG((dev_info_t *)NULL, sw_label, SCSI_DEBUG,
 236             "scsi_watch_request_submit: Entering ...\n");
 237 
 238         mutex_enter(&sw.sw_mutex);
 239         if (sw.sw_thread == 0) {
 240                 register kthread_t      *t;
 241 
 242                 t = thread_create((caddr_t)NULL, 0, scsi_watch_thread,
 243                     NULL, 0, &p0, TS_RUN, v.v_maxsyspri - 2);
 244                 sw.sw_thread = t;
 245         }
 246 
 247         for (p = sw.sw_head; p != NULL; p = p->swr_next) {
 248                 if ((p->swr_callback_arg == cb_arg) &&
 249                     (p->swr_callback == callback))
 250                         break;
 251         }
 252 
 253         /* update time interval for an existing request */
 254         if (p) {
 255                 if (p->swr_what != SWR_STOP) {
 256                         p->swr_timeout = p->swr_interval
 257                             = drv_usectohz(interval);
 258                         p->swr_what = SWR_WATCH;
 259                         p->swr_ref++;
 260                         cv_signal(&sw.sw_cv);
 261                         mutex_exit(&sw.sw_mutex);
 262                         return ((opaque_t)p);
 263                 }
 264         }
 265         mutex_exit(&sw.sw_mutex);
 266 
 267         /*
 268          * allocate space for scsi_watch_request
 269          */
 270         swr = kmem_zalloc(sizeof (struct scsi_watch_request), KM_SLEEP);
 271 
 272         /*
 273          * allocate request sense bp and pkt and make cmd
 274          * we shouldn't really need it if ARQ is enabled but it is useful
 275          * if the ARQ failed.
 276          */
 277         bp = scsi_alloc_consistent_buf(ROUTE, NULL,
 278             sense_length, B_READ, SLEEP_FUNC, NULL);
 279 
 280         rqpkt = scsi_init_pkt(ROUTE, (struct scsi_pkt *)NULL,
 281             bp, CDB_GROUP0, 1, 0, PKT_CONSISTENT, SLEEP_FUNC, NULL);
 282 
 283         (void) scsi_setup_cdb((union scsi_cdb *)rqpkt->pkt_cdbp,
 284             SCMD_REQUEST_SENSE, 0, SENSE_LENGTH, 0);
 285         FILL_SCSI1_LUN(devp, rqpkt);
 286         rqpkt->pkt_private = (opaque_t)swr;
 287         rqpkt->pkt_time = scsi_watch_io_time;
 288         rqpkt->pkt_comp = scsi_watch_request_intr;
 289         rqpkt->pkt_flags |= FLAG_HEAD;
 290 
 291         /*
 292          * Create TUR pkt or GET STATUS EVENT NOTIFICATION for MMC requests or
 293          * a zero byte WRITE(10) based on the disk-type for reservation state.
 294          * For inq_dtype of SBC (DIRECT, dtype == 0)
 295          * OR for RBC devices (dtype is 0xE) AND for
 296          * ANSI version of SPC/SPC-2/SPC-3 (inq_ansi == 3-5).
 297          */
 298 
 299         dtype = devp->sd_inq->inq_dtype & DTYPE_MASK;
 300         if (mmc) {
 301                 mmcbp = scsi_alloc_consistent_buf(ROUTE, NULL,
 302                     8, B_READ, SLEEP_FUNC, NULL);
 303 
 304                 pkt = scsi_init_pkt(ROUTE, (struct scsi_pkt *)NULL, mmcbp,
 305                     CDB_GROUP1, sizeof (struct scsi_arq_status),
 306                     0, 0, SLEEP_FUNC, NULL);
 307 
 308                 (void) scsi_setup_cdb((union scsi_cdb *)pkt->pkt_cdbp,
 309                     SCMD_GET_EVENT_STATUS_NOTIFICATION, 0, 8, 0);
 310                 pkt->pkt_cdbp[1] = 1; /* polled */
 311                 pkt->pkt_cdbp[4] = 1 << SD_GESN_MEDIA_CLASS;
 312         } else if (((dtype == 0) || (dtype == 0xE)) &&
 313             (devp->sd_inq->inq_ansi > 2)) {
 314                 pkt = scsi_init_pkt(ROUTE, (struct scsi_pkt *)NULL, NULL,
 315                     CDB_GROUP1, sizeof (struct scsi_arq_status),
 316                     0, 0, SLEEP_FUNC, NULL);
 317 
 318                 (void) scsi_setup_cdb((union scsi_cdb *)pkt->pkt_cdbp,
 319                     SCMD_WRITE_G1, 0, 0, 0);
 320         } else {
 321                 pkt = scsi_init_pkt(ROUTE, (struct scsi_pkt *)NULL, NULL,
 322                     CDB_GROUP0, sizeof (struct scsi_arq_status),
 323                     0, 0, SLEEP_FUNC, NULL);
 324 
 325                 (void) scsi_setup_cdb((union scsi_cdb *)pkt->pkt_cdbp,
 326                     SCMD_TEST_UNIT_READY, 0, 0, 0);
 327                 FILL_SCSI1_LUN(devp, pkt);
 328         }
 329 
 330         pkt->pkt_private = (opaque_t)swr;
 331         pkt->pkt_time = scsi_watch_io_time;
 332         pkt->pkt_comp = scsi_watch_request_intr;
 333         if (scsi_ifgetcap(&pkt->pkt_address, "tagged-qing", 1) == 1) {
 334                 pkt->pkt_flags |= FLAG_STAG;
 335         }
 336 
 337         /*
 338          * set the allocated resources in swr
 339          */
 340         swr->swr_rqbp = bp;
 341         swr->swr_rqpkt = rqpkt;
 342         swr->swr_mmcbp = mmcbp;
 343         swr->swr_pkt = pkt;
 344         swr->swr_timeout = swr->swr_interval = drv_usectohz(interval);
 345         swr->swr_callback = callback;
 346         swr->swr_callback_arg = cb_arg;
 347         swr->swr_what = SWR_WATCH;
 348         swr->swr_sense_length = (uchar_t)sense_length;
 349         swr->swr_ref = 1;
 350         cv_init(&swr->swr_terminate_cv, NULL, CV_DRIVER, NULL);
 351 
 352         /*
 353          * add to the list and wake up the thread
 354          */
 355         mutex_enter(&sw.sw_mutex);
 356         swr->swr_next = sw.sw_head;
 357         swr->swr_prev = NULL;
 358         if (sw.sw_head) {
 359                 sw.sw_head->swr_prev = swr;
 360         }
 361         sw.sw_head = swr;
 362 
 363         /*
 364          * reset all timeouts, so all requests are in sync again
 365          * XXX there is a small window where the watch thread releases
 366          * the mutex so that could upset the resyncing
 367          */
 368         sswr = swr;
 369         while (sswr) {
 370                 sswr->swr_timeout = swr->swr_interval;
 371                 sswr = sswr->swr_next;
 372         }
 373         cv_signal(&sw.sw_cv);
 374         mutex_exit(&sw.sw_mutex);
 375         return ((opaque_t)swr);
 376 }
 377 
 378 
 379 /*
 380  * called by (eg. pwr management) to resume the scsi_watch_thread
 381  */
 382 void
 383 scsi_watch_resume(opaque_t token)
 384 {
 385         struct scsi_watch_request *swr = (struct scsi_watch_request *)NULL;
 386         /*
 387          * Change the state to SW_RUNNING and wake up the scsi_watch_thread
 388          */
 389         SW_DEBUG(0, sw_label, SCSI_DEBUG, "scsi_watch_resume:\n");
 390         mutex_enter(&sw.sw_mutex);
 391 
 392         if (!sw.sw_head)
 393                 goto exit;
 394 
 395         /* search for token */
 396         for (swr = sw.sw_head; swr; swr = swr->swr_next) {
 397                 if (swr == (struct scsi_watch_request *)token)
 398                         break;
 399         }
 400 
 401         /* if we can't find this value, then we just do nothing */
 402         if (swr == (struct scsi_watch_request *)NULL)
 403                 goto exit;
 404 
 405         swr->swr_what = SWR_WATCH;
 406 
 407 
 408         /* see if all swr's are awake, then start the thread again */
 409         for (swr = sw.sw_head; swr; swr = swr->swr_next) {
 410                 if (swr->swr_what != SWR_WATCH)
 411                         goto exit;
 412         }
 413 
 414         sw.sw_state = SW_RUNNING;
 415         cv_signal(&sw.sw_cv);
 416 
 417 exit:
 418         mutex_exit(&sw.sw_mutex);
 419 }
 420 
 421 
 422 /*
 423  * called by clients (eg. pwr management) to suspend the scsi_watch_thread
 424  */
 425 void
 426 scsi_watch_suspend(opaque_t token)
 427 {
 428         struct scsi_watch_request *swr = (struct scsi_watch_request *)NULL;
 429         clock_t halfsec_delay = drv_usectohz(500000);
 430 
 431         SW_DEBUG(0, sw_label, SCSI_DEBUG, "scsi_watch_suspend:\n");
 432 
 433         mutex_enter(&sw.sw_mutex);
 434 
 435         if (!sw.sw_head)
 436                 goto exit;
 437 
 438         /* search for token */
 439         for (swr = sw.sw_head; swr; swr = swr->swr_next) {
 440                 if (swr == (struct scsi_watch_request *)token)
 441                         break;
 442         }
 443 
 444         /* if we can't find this value, then we just do nothing */
 445         if (swr == (struct scsi_watch_request *)NULL)
 446                 goto exit;
 447 
 448 
 449         for (;;) {
 450                 if (swr->swr_busy) {
 451                         /*
 452                          * XXX: Assumes that this thread can rerun
 453                          * till all outstanding cmds are complete
 454                          */
 455                         swr->swr_what = SWR_SUSPEND_REQUESTED;
 456                         (void) cv_reltimedwait(&sw.sw_cv, &sw.sw_mutex,
 457                             halfsec_delay, TR_CLOCK_TICK);
 458                 } else {
 459                         swr->swr_what = SWR_SUSPENDED;
 460                         break;
 461                 }
 462         }
 463 
 464         /* see if all swr's are suspended, then suspend the thread */
 465         for (swr = sw.sw_head; swr; swr = swr->swr_next) {
 466                 if (swr->swr_what != SWR_SUSPENDED)
 467                         goto exit;
 468         }
 469 
 470         sw.sw_state = SW_SUSPENDED;
 471 
 472 exit:
 473         mutex_exit(&sw.sw_mutex);
 474 }
 475 
 476 /*
 477  * destroy swr, called for watch thread
 478  */
 479 static void
 480 scsi_watch_request_destroy(struct scsi_watch_request *swr)
 481 {
 482         ASSERT(MUTEX_HELD(&sw.sw_mutex));
 483         ASSERT(swr->swr_busy == 0);
 484 
 485         SW_DEBUG((dev_info_t *)NULL, sw_label, SCSI_DEBUG,
 486             "scsi_watch_request_destroy: Entering ...\n");
 487         if (swr->swr_ref != 0)
 488                 return;
 489 
 490         /*
 491          * remove swr from linked list and destroy pkts
 492          */
 493         if (swr->swr_prev) {
 494                 swr->swr_prev->swr_next = swr->swr_next;
 495         }
 496         if (swr->swr_next) {
 497                 swr->swr_next->swr_prev = swr->swr_prev;
 498         }
 499         if (sw.sw_head == swr) {
 500                 sw.sw_head = swr->swr_next;
 501         }
 502         if (sw.swr_current == swr) {
 503                 swr->suspend_destroy = SUSPEND_DESTROY;
 504                 sw.swr_current = NULL;
 505         }
 506 
 507         scsi_destroy_pkt(swr->swr_rqpkt);
 508         scsi_free_consistent_buf(swr->swr_rqbp);
 509         if (swr->swr_mmcbp != NULL) {
 510                 scsi_free_consistent_buf(swr->swr_mmcbp);
 511         }
 512         scsi_destroy_pkt(swr->swr_pkt);
 513         cv_signal(&swr->swr_terminate_cv);
 514 }
 515 
 516 /*
 517  * scsi_watch_request_terminate()
 518  * called by requestor to terminate any pending watch request.
 519  * if the request is currently "busy", and the caller cannot wait, failure
 520  * is returned. O/w the request is cleaned up immediately.
 521  */
 522 int
 523 scsi_watch_request_terminate(opaque_t token, int flags)
 524 {
 525         struct scsi_watch_request *swr =
 526             (struct scsi_watch_request *)token;
 527         struct scsi_watch_request *sswr;
 528 
 529         int count = 0;
 530         int free_flag = 0;
 531 
 532         /*
 533          * We try to clean up this request if we can. We also inform
 534          * the watch thread that we mucked around the list so it has
 535          * to start reading from head of list again.
 536          */
 537         SW_DEBUG((dev_info_t *)NULL, sw_label, SCSI_DEBUG,
 538             "scsi_watch_request_terminate: Entering(0x%p) ...\n",
 539             (void *)swr);
 540         mutex_enter(&sw.sw_mutex);
 541 
 542         /*
 543          * check if it is still in the list
 544          */
 545         sswr = sw.sw_head;
 546         while (sswr) {
 547                 if (sswr == swr) {
 548                         swr->swr_ref--;
 549                         count = swr->swr_ref;
 550 
 551                         if (swr->swr_busy) {
 552                                 if (flags == SCSI_WATCH_TERMINATE_NOWAIT) {
 553                                         mutex_exit(&sw.sw_mutex);
 554                                         return (SCSI_WATCH_TERMINATE_FAIL);
 555                                 }
 556                                 if (count != 0 && flags !=
 557                                     SCSI_WATCH_TERMINATE_ALL_WAIT) {
 558                                         mutex_exit(&sw.sw_mutex);
 559                                         return (SCSI_WATCH_TERMINATE_SUCCESS);
 560                                 }
 561                                 if (SCSI_WATCH_TERMINATE_ALL_WAIT == flags) {
 562                                         swr->swr_ref = 0;
 563                                         count = 0;
 564                                 }
 565                                 swr->swr_what = SWR_STOP;
 566                                 cv_wait(&swr->swr_terminate_cv, &sw.sw_mutex);
 567                                 free_flag = 1;
 568                                 goto done;
 569                         } else {
 570                                 if (SCSI_WATCH_TERMINATE_NOWAIT == flags ||
 571                                     SCSI_WATCH_TERMINATE_ALL_WAIT == flags) {
 572                                         swr->swr_ref = 0;
 573                                         count = 0;
 574                                 }
 575                                 scsi_watch_request_destroy(swr);
 576                                 if (0 == count) {
 577                                         sw.sw_flags |= SW_START_HEAD;
 578                                         free_flag = 1;
 579                                 }
 580                                 goto done;
 581                         }
 582                 }
 583                 sswr = sswr->swr_next;
 584         }
 585 done:
 586         mutex_exit(&sw.sw_mutex);
 587         if (!sswr) {
 588                 return (SCSI_WATCH_TERMINATE_FAIL);
 589         }
 590         if (1 == free_flag &&
 591             sswr->suspend_destroy != SUSPEND_DESTROY) {
 592                 cv_destroy(&swr->swr_terminate_cv);
 593                 kmem_free((caddr_t)swr, sizeof (struct scsi_watch_request));
 594         }
 595 
 596         return (SCSI_WATCH_TERMINATE_SUCCESS);
 597 }
 598 
 599 
 600 /*
 601  * The routines scsi_watch_thread & scsi_watch_request_intr are
 602  * on different threads.
 603  * If there is no work to be done by the lower level driver
 604  * then swr->swr_busy will not be set.
 605  * In this case we will call CALLB_CPR_SAFE_BEGIN before
 606  * calling cv_timedwait.
 607  * In the other case where there is work to be done by
 608  * the lower level driver then the flag swr->swr_busy will
 609  * be set.
 610  * We cannot call CALLB_CPR_SAFE_BEGIN at this point the reason
 611  * is the intr thread can interfere with our operations. So
 612  * we do a cv_timedwait here. Now at the completion of the
 613  * lower level driver's work we will call CALLB_CPR_SAFE_BEGIN
 614  * in scsi_watch_request_intr.
 615  * In all the cases we will call CALLB_CPR_SAFE_END only if
 616  * we already called a CALLB_CPR_SAFE_BEGIN and this is flagged
 617  * by sw_cpr_flag.
 618  * Warlock has a problem when we use different locks
 619  * on the same type of structure in different contexts.
 620  * We use callb_cpr_t in both scsi_watch and esp_callback threads.
 621  * we use different mutexe's in different threads. And
 622  * this is not acceptable to warlock. To avoid this
 623  * problem we use the same name for the mutex in
 624  * both scsi_watch & esp_callback. when __lock_lint is not defined
 625  * esp_callback uses the mutex on the stack and in scsi_watch
 626  * a static variable. But when __lock_lint is defined
 627  * we make a mutex which is global in esp_callback and
 628  * a external mutex for scsi_watch.
 629  */
 630 static int sw_cmd_count = 0;
 631 static int sw_cpr_flag = 0;
 632 static callb_cpr_t cpr_info;
 633 #ifndef __lock_lint
 634 static kmutex_t cpr_mutex;
 635 #else
 636 extern kmutex_t cpr_mutex;
 637 #endif
 638 
 639 #if !defined(lint)
 640 _NOTE(MUTEX_PROTECTS_DATA(cpr_mutex, cpr_info))
 641 _NOTE(MUTEX_PROTECTS_DATA(cpr_mutex, sw_cmd_count))
 642 #endif
 643 /*
 644  * the scsi watch thread:
 645  * it either wakes up if there is work to do or if the cv_timeait
 646  * timed out
 647  * normally, it wakes up every <delay> seconds and checks the list.
 648  * the interval is not very accurate if the cv was signalled but that
 649  * really doesn't matter much
 650  * it is more important that we fire off all TURs simulataneously so
 651  * we don't have to wake up frequently
 652  */
 653 static void
 654 scsi_watch_thread()
 655 {
 656         struct scsi_watch_request       *swr, *next;
 657         clock_t                         last_delay = 0;
 658         clock_t                         next_delay = 0;
 659         clock_t                         onesec = drv_sectohz(1);
 660         clock_t                         exit_delay = 60 * onesec;
 661 
 662         SW_DEBUG((dev_info_t *)NULL, sw_label, SCSI_DEBUG,
 663             "scsi_watch_thread: Entering ...\n");
 664 
 665 #if !defined(lint)
 666         _NOTE(NO_COMPETING_THREADS_NOW);
 667 #endif
 668         mutex_init(&cpr_mutex, NULL, MUTEX_DRIVER, NULL);
 669         CALLB_CPR_INIT(&cpr_info,
 670             &cpr_mutex, callb_generic_cpr, "scsi_watch");
 671         sw_cpr_flag = 0;
 672 #if !defined(lint)
 673         /*LINTED*/
 674         _NOTE(COMPETING_THREADS_NOW);
 675 #endif
 676         /*
 677          * grab the mutex and wait for work
 678          */
 679         mutex_enter(&sw.sw_mutex);
 680         if (sw.sw_head == NULL) {
 681                 cv_wait(&sw.sw_cv, &sw.sw_mutex);
 682         }
 683 
 684         /*
 685          * now loop forever for work; if queue is empty exit
 686          */
 687         for (;;) {
 688 head:
 689                 swr = sw.sw_head;
 690                 while (swr) {
 691 
 692                         /*
 693                          * If state is not running, wait for scsi_watch_resume
 694                          * to signal restart, but before going into cv_wait
 695                          * need to let the PM framework know that it is safe
 696                          * to stop this thread for CPR
 697                          */
 698                         if (sw.sw_state != SW_RUNNING) {
 699                                 SW_DEBUG(0, sw_label, SCSI_DEBUG,
 700                                     "scsi_watch_thread suspended\n");
 701                                 mutex_enter(&cpr_mutex);
 702                                 if (!sw_cmd_count) {
 703                                         CALLB_CPR_SAFE_BEGIN(&cpr_info);
 704                                         sw_cpr_flag = 1;
 705                                 }
 706                                 mutex_exit(&cpr_mutex);
 707                                 sw.swr_current = swr;
 708                                 cv_wait(&sw.sw_cv, &sw.sw_mutex);
 709 
 710 
 711                                 /*
 712                                  * Need to let the PM framework know that it
 713                                  * is no longer safe to stop the thread for
 714                                  * CPR.
 715                                  */
 716                                 mutex_exit(&sw.sw_mutex);
 717                                 mutex_enter(&cpr_mutex);
 718                                 if (sw_cpr_flag == 1) {
 719                                         CALLB_CPR_SAFE_END(
 720                                             &cpr_info, &cpr_mutex);
 721                                         sw_cpr_flag = 0;
 722                                 }
 723                                 mutex_exit(&cpr_mutex);
 724                                 mutex_enter(&sw.sw_mutex);
 725                                 if (SUSPEND_DESTROY == swr->suspend_destroy) {
 726                                         cv_destroy(&swr->swr_terminate_cv);
 727                                         kmem_free((caddr_t)swr,
 728                                             sizeof (struct scsi_watch_request));
 729                                         goto head;
 730                                 } else {
 731                                         sw.swr_current = NULL;
 732                                 }
 733                         }
 734                         if (next_delay == 0) {
 735                                 next_delay = swr->swr_timeout;
 736                         } else {
 737                                 next_delay = min(swr->swr_timeout, next_delay);
 738                         }
 739 
 740                         swr->swr_timeout -= last_delay;
 741                         next = swr->swr_next;
 742 
 743                         SW_DEBUG((dev_info_t *)NULL, sw_label, SCSI_DEBUG,
 744                             "scsi_watch_thread: "
 745                             "swr(0x%p),what=%x,timeout=%lx,"
 746                             "interval=%lx,delay=%lx\n",
 747                             (void *)swr, swr->swr_what, swr->swr_timeout,
 748                             swr->swr_interval, last_delay);
 749 
 750                         switch (swr->swr_what) {
 751                         case SWR_SUSPENDED:
 752                         case SWR_SUSPEND_REQUESTED:
 753                                 /* if we are suspended, don't do anything */
 754                                 break;
 755 
 756                         case SWR_STOP:
 757                                 if (swr->swr_busy == 0) {
 758                                         scsi_watch_request_destroy(swr);
 759                                 }
 760                                 break;
 761 
 762                         default:
 763                                 if (swr->swr_timeout <= 0 && !swr->swr_busy) {
 764                                         swr->swr_busy = 1;
 765                                         swr->swr_timeout = swr->swr_interval;
 766 
 767                                         /*
 768                                          * submit the cmd and let the completion
 769                                          * function handle the result
 770                                          * release the mutex (good practice)
 771                                          * this should be safe even if the list
 772                                          * is changing
 773                                          */
 774                                         mutex_exit(&sw.sw_mutex);
 775                                         mutex_enter(&cpr_mutex);
 776                                         sw_cmd_count++;
 777                                         mutex_exit(&cpr_mutex);
 778                                         SW_DEBUG((dev_info_t *)NULL,
 779                                             sw_label, SCSI_DEBUG,
 780                                             "scsi_watch_thread: "
 781                                             "Starting TUR\n");
 782                                         if (scsi_transport(swr->swr_pkt) !=
 783                                             TRAN_ACCEPT) {
 784 
 785                                                 /*
 786                                                  * try again later
 787                                                  */
 788                                                 swr->swr_busy = 0;
 789                                                 SW_DEBUG((dev_info_t *)NULL,
 790                                                     sw_label, SCSI_DEBUG,
 791                                                     "scsi_watch_thread: "
 792                                                     "Transport Failed\n");
 793                                                 mutex_enter(&cpr_mutex);
 794                                                 sw_cmd_count--;
 795                                                 mutex_exit(&cpr_mutex);
 796                                         }
 797                                         mutex_enter(&sw.sw_mutex);
 798                                 }
 799                                 break;
 800                         }
 801                         swr = next;
 802                         if (sw.sw_flags & SW_START_HEAD) {
 803                                 sw.sw_flags &= ~SW_START_HEAD;
 804                                 goto head;
 805                         }
 806                 }
 807 
 808                 /*
 809                  * delay using cv_timedwait; we return when
 810                  * signalled or timed out
 811                  */
 812                 if (sw.sw_head != NULL) {
 813                         if (next_delay <= 0) {
 814                                 next_delay = onesec;
 815                         }
 816                 } else {
 817                         next_delay = exit_delay;
 818                 }
 819 
 820                 mutex_enter(&cpr_mutex);
 821                 if (!sw_cmd_count) {
 822                         CALLB_CPR_SAFE_BEGIN(&cpr_info);
 823                         sw_cpr_flag = 1;
 824                 }
 825                 mutex_exit(&cpr_mutex);
 826                 /*
 827                  * if we return from cv_timedwait because we were
 828                  * signalled, the delay is not accurate but that doesn't
 829                  * really matter
 830                  */
 831                 (void) cv_reltimedwait(&sw.sw_cv, &sw.sw_mutex, next_delay,
 832                     TR_CLOCK_TICK);
 833                 mutex_exit(&sw.sw_mutex);
 834                 mutex_enter(&cpr_mutex);
 835                 if (sw_cpr_flag == 1) {
 836                         CALLB_CPR_SAFE_END(&cpr_info, &cpr_mutex);
 837                         sw_cpr_flag = 0;
 838                 }
 839                 mutex_exit(&cpr_mutex);
 840                 mutex_enter(&sw.sw_mutex);
 841                 last_delay = next_delay;
 842                 next_delay = 0;
 843 
 844                 /*
 845                  * is there still work to do?
 846                  */
 847                 if (sw.sw_head == NULL) {
 848                         break;
 849                 }
 850         }
 851 
 852         /*
 853          * no more work to do, reset sw_thread and exit
 854          */
 855         sw.sw_thread = 0;
 856         mutex_exit(&sw.sw_mutex);
 857 #ifndef __lock_lint
 858         mutex_enter(&cpr_mutex);
 859         CALLB_CPR_EXIT(&cpr_info);
 860 #endif
 861         mutex_destroy(&cpr_mutex);
 862         SW_DEBUG((dev_info_t *)NULL, sw_label, SCSI_DEBUG,
 863             "scsi_watch_thread: Exiting ...\n");
 864 }
 865 
 866 /*
 867  * callback completion function for scsi watch pkt
 868  */
 869 #define SCBP(pkt)       ((struct scsi_status *)(pkt)->pkt_scbp)
 870 #define SCBP_C(pkt)     ((*(pkt)->pkt_scbp) & STATUS_MASK)
 871 
 872 static void
 873 scsi_watch_request_intr(struct scsi_pkt *pkt)
 874 {
 875         struct scsi_watch_result        result;
 876         struct scsi_watch_request       *swr =
 877             (struct scsi_watch_request *)pkt->pkt_private;
 878         struct scsi_status              *rqstatusp;
 879         struct scsi_extended_sense      *rqsensep = NULL;
 880         int                             amt = 0;
 881 
 882         SW_DEBUG((dev_info_t *)NULL, sw_label, SCSI_DEBUG,
 883             "scsi_watch_intr: Entering ...\n");
 884 
 885         /*
 886          * first check if it is the TUR or RQS pkt
 887          */
 888         if (pkt == swr->swr_pkt) {
 889                 if (SCBP_C(pkt) != STATUS_GOOD &&
 890                     SCBP_C(pkt) != STATUS_RESERVATION_CONFLICT) {
 891                         if (SCBP(pkt)->sts_chk &&
 892                             ((pkt->pkt_state & STATE_ARQ_DONE) == 0)) {
 893 
 894                                 /*
 895                                  * submit the request sense pkt
 896                                  */
 897                                 SW_DEBUG((dev_info_t *)NULL,
 898                                     sw_label, SCSI_DEBUG,
 899                                     "scsi_watch_intr: "
 900                                     "Submitting a Request Sense "
 901                                     "Packet\n");
 902                                 if (scsi_transport(swr->swr_rqpkt) !=
 903                                     TRAN_ACCEPT) {
 904 
 905                                         /*
 906                                          * just give up and try again later
 907                                          */
 908                                         SW_DEBUG((dev_info_t *)NULL,
 909                                             sw_label, SCSI_DEBUG,
 910                                             "scsi_watch_intr: "
 911                                             "Request Sense "
 912                                             "Transport Failed\n");
 913                                         goto done;
 914                                 }
 915 
 916                                 /*
 917                                  * wait for rqsense to complete
 918                                  */
 919                                 return;
 920 
 921                         } else  if (SCBP(pkt)->sts_chk) {
 922 
 923                                 /*
 924                                  * check the autorequest sense data
 925                                  */
 926                                 struct scsi_arq_status  *arqstat =
 927                                     (struct scsi_arq_status *)pkt->pkt_scbp;
 928 
 929                                 rqstatusp = &arqstat->sts_rqpkt_status;
 930                                 rqsensep = &arqstat->sts_sensedata;
 931                                 amt = swr->swr_sense_length -
 932                                     arqstat->sts_rqpkt_resid;
 933                                 SW_DEBUG((dev_info_t *)NULL,
 934                                     sw_label, SCSI_DEBUG,
 935                                     "scsi_watch_intr: "
 936                                     "Auto Request Sense, amt=%x\n", amt);
 937                         }
 938                 }
 939 
 940         } else if (pkt == swr->swr_rqpkt) {
 941 
 942                 /*
 943                  * check the request sense data
 944                  */
 945                 rqstatusp = (struct scsi_status *)pkt->pkt_scbp;
 946                 rqsensep = (struct scsi_extended_sense *)
 947                     swr->swr_rqbp->b_un.b_addr;
 948                 amt = swr->swr_sense_length - pkt->pkt_resid;
 949                 SW_DEBUG((dev_info_t *)NULL, sw_label, SCSI_DEBUG,
 950                     "scsi_watch_intr: "
 951                     "Request Sense Completed, amt=%x\n", amt);
 952         } else {
 953 
 954                 /*
 955                  * should not reach here!!!
 956                  */
 957                 scsi_log((dev_info_t *)NULL, sw_label, CE_PANIC,
 958                     "scsi_watch_intr: Bad Packet(0x%p)", (void *)pkt);
 959         }
 960 
 961         if (rqsensep) {
 962 
 963                 /*
 964                  * check rqsense status and data
 965                  */
 966                 if (rqstatusp->sts_busy || rqstatusp->sts_chk) {
 967 
 968                         /*
 969                          * try again later
 970                          */
 971                         SW_DEBUG((dev_info_t *)NULL, sw_label, SCSI_DEBUG,
 972                             "scsi_watch_intr: "
 973                             "Auto Request Sense Failed - "
 974                             "Busy or Check Condition\n");
 975                         goto done;
 976                 }
 977 
 978                 SW_DEBUG((dev_info_t *)NULL, sw_label, SCSI_DEBUG,
 979                     "scsi_watch_intr: "
 980                     "es_key=%x, adq=%x, amt=%x\n",
 981                     rqsensep->es_key, rqsensep->es_add_code, amt);
 982         }
 983 
 984         /*
 985          * callback to target driver to do the real work
 986          */
 987         result.statusp = SCBP(swr->swr_pkt);
 988         result.sensep = rqsensep;
 989         result.actual_sense_length = (uchar_t)amt;
 990         result.pkt = swr->swr_pkt;
 991         if (swr->swr_mmcbp != NULL) {
 992                 bcopy(swr->swr_mmcbp->b_un.b_addr, result.mmc_data, 8);
 993         }
 994 
 995         if ((*swr->swr_callback)(swr->swr_callback_arg, &result)) {
 996                 swr->swr_what = SWR_STOP;
 997         }
 998 
 999 done:
1000         swr->swr_busy = 0;
1001         mutex_enter(&cpr_mutex);
1002         sw_cmd_count --;
1003         if (!sw_cmd_count) {
1004                 CALLB_CPR_SAFE_BEGIN(&cpr_info);
1005                 sw_cpr_flag = 1;
1006         }
1007         mutex_exit(&cpr_mutex);
1008 }
1009 
1010 /*
1011  * scsi_watch_get_ref_count
1012  * called by clients to query the reference count for a given token.
1013  * return the number of reference count or 0 if the given token is
1014  * not found.
1015  */
1016 int
1017 scsi_watch_get_ref_count(opaque_t token)
1018 {
1019         struct scsi_watch_request *swr =
1020             (struct scsi_watch_request *)token;
1021         struct scsi_watch_request *sswr;
1022         int rval = 0;
1023 
1024         SW_DEBUG((dev_info_t *)NULL, sw_label, SCSI_DEBUG,
1025             "scsi_watch_get_ref_count: Entering(0x%p) ...\n",
1026             (void *)swr);
1027         mutex_enter(&sw.sw_mutex);
1028 
1029         sswr = sw.sw_head;
1030         while (sswr) {
1031                 if (sswr == swr) {
1032                         rval = swr->swr_ref;
1033                         mutex_exit(&sw.sw_mutex);
1034                         return (rval);
1035                 }
1036                 sswr = sswr->swr_next;
1037         }
1038 
1039         mutex_exit(&sw.sw_mutex);
1040         return (rval);
1041 }