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  * SBP2 module
  28  */
  29 #include <sys/param.h>
  30 #include <sys/errno.h>
  31 #include <sys/cred.h>
  32 #include <sys/conf.h>
  33 #include <sys/disp.h>
  34 #include <sys/modctl.h>
  35 #include <sys/stat.h>
  36 #include <sys/stream.h>
  37 #include <sys/strsubr.h>
  38 #include <sys/strsun.h>
  39 #include <sys/ddi.h>
  40 #include <sys/sunddi.h>
  41 
  42 #include <sys/sbp2/impl.h>
  43 #include <sys/1394/ieee1212.h>
  44 
  45 /* target routines */
  46 static void     sbp2_tgt_init_sobj(sbp2_tgt_t *);
  47 static void     sbp2_tgt_fini_sobj(sbp2_tgt_t *);
  48 static int      sbp2_tgt_init_params(sbp2_tgt_t *);
  49 static int      sbp2_tgt_init_luns(sbp2_tgt_t *, int);
  50 static void     sbp2_tgt_fini_luns(sbp2_tgt_t *);
  51 static int      sbp2_tgt_init_bus(sbp2_tgt_t *);
  52 static void     sbp2_tgt_fini_bus(sbp2_tgt_t *);
  53 static int      sbp2_tgt_mgt_request(sbp2_tgt_t *, int *);
  54 static int      sbp2_tgt_task_mgt_request(sbp2_tgt_t *, uint16_t, int, uint64_t,
  55                 int *);
  56 
  57 /* lun routines */
  58 static void     sbp2_lun_logout_orb(sbp2_lun_t *, sbp2_tgt_t *, int *);
  59 static boolean_t sbp2_lun_accepting_tasks(sbp2_lun_t *);
  60 
  61 /* session routines */
  62 static int      sbp2_ses_init(sbp2_ses_t **, sbp2_lun_t *,
  63                 void (*)(void *, sbp2_task_t *), void *);
  64 static void     sbp2_ses_fini(sbp2_ses_t *);
  65 static sbp2_task_t *sbp2_ses_orbp2task(sbp2_ses_t *, uint64_t);
  66 static void     sbp2_ses_append_task(sbp2_ses_t *, sbp2_task_t *);
  67 static void     sbp2_ses_reset_pending_tasks(sbp2_ses_t *, uint16_t);
  68 static int      sbp2_ses_reconnect_orb(sbp2_ses_t *, int *);
  69 
  70 /* orb alloc routines */
  71 static sbp2_bus_buf_t *sbp2_orb_freelist_get(sbp2_lun_t *, sbp2_task_t *, int);
  72 static int      sbp2_orb_freelist_put(sbp2_lun_t *, sbp2_bus_buf_t *);
  73 static void     sbp2_orb_freelist_destroy(sbp2_lun_t *);
  74 
  75 /* fetch agent routines */
  76 static int      sbp2_agent_init(sbp2_agent_t *, uint64_t, sbp2_tgt_t *tp);
  77 static void     sbp2_agent_fini(sbp2_agent_t *);
  78 static void     sbp2_agent_acquire_locked(sbp2_agent_t *);
  79 static void     sbp2_agent_release_locked(sbp2_agent_t *);
  80 static void     sbp2_agent_acquire(sbp2_agent_t *);
  81 static void     sbp2_agent_release(sbp2_agent_t *);
  82 static int      sbp2_agent_keepalive(sbp2_agent_t *, int *);
  83 static int      sbp2_agent_doorbell(sbp2_agent_t *, int *);
  84 static int      sbp2_agent_write_orbp(sbp2_agent_t *, uint64_t, int *);
  85 static int      sbp2_agent_reset(sbp2_agent_t *, int *);
  86 
  87 /* callbacks and timeouts */
  88 static void     sbp2_mgt_status_fifo_wb_cb(sbp2_bus_buf_t *, void *, mblk_t **);
  89 static void     sbp2_task_timeout(void *);
  90 static void     sbp2_status_fifo_wb_cb(sbp2_bus_buf_t *, void *, mblk_t **);
  91 
  92 /* other */
  93 static void     sbp2_mgt_agent_acquire(sbp2_tgt_t *);
  94 static void     sbp2_mgt_agent_release(sbp2_tgt_t *);
  95 static void     sbp2_fetch_agent_acquire(sbp2_ses_t *);
  96 static void     sbp2_fetch_agent_release(sbp2_ses_t *);
  97 
  98 extern struct mod_ops mod_miscops;
  99 
 100 static struct modlmisc sbp2_modlmisc = {
 101         &mod_miscops,               /* module type */
 102         "Serial Bus Protocol 2 module" /* module name */
 103 };
 104 
 105 static struct modlinkage sbp2_modlinkage = {
 106         MODREV_1, (void *)&sbp2_modlmisc, NULL
 107 };
 108 
 109 /* tunables */
 110 int     sbp2_submit_reset_nretries = 3;
 111 clock_t sbp2_submit_reset_delay = 10;   /* microsec */
 112 
 113 int     sbp2_write_orbp_nretries = 3;
 114 clock_t sbp2_write_orbp_delay = 10;     /* microsec */
 115 
 116 _NOTE(SCHEME_PROTECTS_DATA("unique per call", datab msgb))
 117 
 118 /*
 119  *
 120  * --- loadable module entry points
 121  *
 122  */
 123 int
 124 _init(void)
 125 {
 126         return (mod_install(&sbp2_modlinkage));
 127 }
 128 
 129 
 130 int
 131 _fini(void)
 132 {
 133         return (mod_remove(&sbp2_modlinkage));
 134 }
 135 
 136 
 137 int
 138 _info(struct modinfo *modinfop)
 139 {
 140         return (mod_info(&sbp2_modlinkage, modinfop));
 141 }
 142 
 143 /*
 144  *
 145  * --- target routines
 146  *
 147  */
 148 int
 149 sbp2_tgt_init(void *bus_hdl, sbp2_bus_t *bus, int maxluns, sbp2_tgt_t **tpp)
 150 {
 151         sbp2_tgt_t      *tp;
 152         int             ret;
 153 
 154         tp = kmem_zalloc(sizeof (sbp2_tgt_t), KM_SLEEP);
 155         tp->t_bus = bus;
 156         tp->t_bus_hdl = bus_hdl;
 157 
 158         sbp2_tgt_init_sobj(tp);
 159 
 160         if ((ret = sbp2_cfgrom_parse(tp, &tp->t_cfgrom)) != SBP2_SUCCESS) {
 161                 sbp2_tgt_fini_sobj(tp);
 162                 kmem_free(tp, sizeof (sbp2_tgt_t));
 163                 return (SBP2_ECFGROM);
 164         }
 165 
 166         if ((ret = sbp2_tgt_init_params(tp)) != SBP2_SUCCESS) {
 167                 sbp2_cfgrom_free(tp, &tp->t_cfgrom);
 168                 sbp2_tgt_fini_sobj(tp);
 169                 kmem_free(tp, sizeof (sbp2_tgt_t));
 170                 return (ret);
 171         }
 172 
 173         if ((ret = sbp2_tgt_init_luns(tp, maxluns)) != SBP2_SUCCESS) {
 174                 sbp2_cfgrom_free(tp, &tp->t_cfgrom);
 175                 sbp2_tgt_fini_sobj(tp);
 176                 kmem_free(tp, sizeof (sbp2_tgt_t));
 177                 return (ret);
 178         }
 179 
 180         if ((ret = sbp2_tgt_init_bus(tp)) != SBP2_SUCCESS) {
 181                 sbp2_tgt_fini_luns(tp);
 182                 sbp2_cfgrom_free(tp, &tp->t_cfgrom);
 183                 sbp2_tgt_fini_sobj(tp);
 184                 kmem_free(tp, sizeof (sbp2_tgt_t));
 185                 return (ret);
 186         }
 187 
 188         *tpp = tp;
 189         return (SBP2_SUCCESS);
 190 }
 191 
 192 void
 193 sbp2_tgt_fini(sbp2_tgt_t *tp)
 194 {
 195         sbp2_tgt_fini_bus(tp);
 196         sbp2_tgt_fini_luns(tp);
 197         sbp2_cfgrom_free(tp, &tp->t_cfgrom);
 198         sbp2_tgt_fini_sobj(tp);
 199         kmem_free(tp, sizeof (sbp2_tgt_t));
 200 }
 201 
 202 static void
 203 sbp2_tgt_init_sobj(sbp2_tgt_t *tp)
 204 {
 205         mutex_init(&tp->t_mutex, NULL, MUTEX_DRIVER, NULL);
 206         cv_init(&tp->t_mgt_agent_cv, NULL, CV_DRIVER, NULL);
 207         cv_init(&tp->t_mgt_status_cv, NULL, CV_DRIVER, NULL);
 208 }
 209 
 210 static void
 211 sbp2_tgt_fini_sobj(sbp2_tgt_t *tp)
 212 {
 213         cv_destroy(&tp->t_mgt_status_cv);
 214         cv_destroy(&tp->t_mgt_agent_cv);
 215         mutex_destroy(&tp->t_mutex);
 216 }
 217 
 218 static int
 219 sbp2_tgt_init_params(sbp2_tgt_t *tp)
 220 {
 221         sbp2_cfgrom_ent_t *root = &tp->t_cfgrom.cr_root;
 222         sbp2_cfgrom_ent_t *ent;
 223         uint32_t        q;
 224 
 225         /* MANAGEMENT_AGENT */
 226         if ((ent = sbp2_cfgrom_ent_by_key(root, SBP2_KT_MGT_AGENT,
 227             SBP2_KV_MGT_AGENT, 0)) == NULL) {
 228                 return (SBP2_ECFGROM);
 229         }
 230         tp->t_mgt_agent = SBP2_CSR_BASE(tp) + ent->ce_data.offset * 4;
 231 
 232         /* Unit_Characteristics */
 233         if ((ent = sbp2_cfgrom_ent_by_key(root, SBP2_KT_UNCHAR,
 234             SBP2_KV_UNCHAR, 0)) == NULL) {
 235                 return (SBP2_ECFGROM);
 236         }
 237         q = ent->ce_data.imm;
 238 
 239         /* units of 500 ms -> ms */
 240         tp->t_mot = ((q & SBP2_UNCHAR_MOT) >> SBP2_UNCHAR_MOT_SHIFT) * 500;
 241 
 242         /* quadlets -> bytes */
 243         tp->t_orb_size = (q & SBP2_UNCHAR_ORB_SIZE) * 4;
 244 
 245         /* some devices return incorrect values */
 246         if (tp->t_mot < SBP2_MOT_MIN) {
 247                 tp->t_mot = SBP2_MOT_DFLT;
 248         }
 249         if (tp->t_orb_size < SBP2_ORB_SIZE_MIN) {
 250                 tp->t_orb_size = SBP2_ORB_SIZE_MIN;
 251         }
 252 
 253         return (SBP2_SUCCESS);
 254 }
 255 
 256 
 257 /*ARGSUSED*/
 258 static int
 259 sbp2_tgt_init_luns(sbp2_tgt_t *tp, int maxluns)
 260 {
 261         sbp2_cfgrom_ent_t *root = &tp->t_cfgrom.cr_root;
 262         sbp2_cfgrom_ent_t *ent;
 263         sbp2_lun_t      *lp;
 264         uint32_t        q;
 265 
 266         ASSERT(tp->t_nluns == 0);
 267 
 268         tp->t_lun = kmem_zalloc(maxluns * sizeof (sbp2_lun_t), KM_SLEEP);
 269         tp->t_nluns_alloc = maxluns;
 270 
 271         /* search for Logical_Unit_Number's */
 272         for (tp->t_nluns = 0; tp->t_nluns < maxluns; tp->t_nluns++) {
 273                 if ((ent = sbp2_cfgrom_ent_by_key(root, SBP2_KT_LUN,
 274                     SBP2_KV_LUN, tp->t_nluns)) == NULL) {
 275                         break;
 276                 }
 277                 q = ent->ce_data.imm;
 278                 lp = &tp->t_lun[tp->t_nluns];
 279                 lp->l_tgt = tp;
 280                 lp->l_lun = q & SBP2_LUN_NUM;
 281                 lp->l_type = (q & SBP2_LUN_TYPE) >> SBP2_LUN_TYPE_SHIFT;
 282                 mutex_init(&lp->l_orb_freelist.bl_mutex, NULL, MUTEX_DRIVER,
 283                     NULL);
 284         }
 285 
 286         if (tp->t_nluns > 0) {
 287                 return (SBP2_SUCCESS);
 288         } else {
 289                 kmem_free(tp->t_lun, tp->t_nluns_alloc * sizeof (sbp2_lun_t));
 290                 return (SBP2_ECFGROM);
 291         }
 292 
 293 }
 294 
 295 
 296 static void
 297 sbp2_tgt_fini_luns(sbp2_tgt_t *tp)
 298 {
 299         int             i;
 300         sbp2_lun_t      *lp;
 301 
 302         /* destroy each lun */
 303         for (i = 0; i < tp->t_nluns; i++) {
 304                 lp = &tp->t_lun[i];
 305                 sbp2_orb_freelist_destroy(lp);
 306                 mutex_destroy(&lp->l_orb_freelist.bl_mutex);
 307         }
 308 
 309         kmem_free(tp->t_lun, tp->t_nluns_alloc * sizeof (sbp2_lun_t));
 310 }
 311 
 312 /*
 313  * initialize bus buffers and commands
 314  */
 315 static int
 316 sbp2_tgt_init_bus(sbp2_tgt_t *tp)
 317 {
 318         int             ret;
 319 
 320         /*
 321          * We serialize management requests and reuse the same buffers.
 322          *
 323          * mgt ORB
 324          */
 325         tp->t_mgt_orb_buf.bb_len =
 326             SBP2_ORB_SIZE_ROUNDUP(tp, sizeof (sbp2_mgt_orb_t));
 327         tp->t_mgt_orb_buf.bb_flags = SBP2_BUS_BUF_DMA | SBP2_BUS_BUF_RD;
 328         if ((ret = SBP2_ALLOC_BUF(tp, &tp->t_mgt_orb_buf)) != SBP2_SUCCESS) {
 329                 sbp2_tgt_fini_bus(tp);
 330                 return (ret);
 331         }
 332 
 333         /*
 334          * mgt status FIFO
 335          */
 336         tp->t_mgt_status_fifo_buf.bb_len = sizeof (sbp2_status_t);
 337         tp->t_mgt_status_fifo_buf.bb_flags = SBP2_BUS_BUF_WR_POSTED;
 338         tp->t_mgt_status_fifo_buf.bb_wb_cb = sbp2_mgt_status_fifo_wb_cb;
 339         tp->t_mgt_status_fifo_buf.bb_sbp2_priv = tp;
 340         if ((ret = SBP2_ALLOC_BUF(tp, &tp->t_mgt_status_fifo_buf)) !=
 341             SBP2_SUCCESS) {
 342                 return (ret);
 343         }
 344 
 345         /*
 346          * login response
 347          */
 348         tp->t_mgt_login_resp_buf.bb_len =
 349             SBP2_ORB_SIZE_ROUNDUP(tp, sizeof (sbp2_login_resp_t));
 350         /*
 351          * read-only should have been sufficient here, but it causes
 352          * DVMA errors on Grover, while read/write works just fine
 353          */
 354         tp->t_mgt_login_resp_buf.bb_flags = SBP2_BUS_BUF_DMA | SBP2_BUS_BUF_RW;
 355         if ((ret = SBP2_ALLOC_BUF(tp, &tp->t_mgt_login_resp_buf)) !=
 356             SBP2_SUCCESS) {
 357                 sbp2_tgt_fini_bus(tp);
 358                 return (ret);
 359         }
 360 
 361         /*
 362          * allocate bus commands
 363          */
 364         if ((ret = SBP2_ALLOC_CMD(tp, &tp->t_mgt_cmd, 0)) != SBP2_SUCCESS) {
 365                 sbp2_tgt_fini_bus(tp);
 366                 return (ret);
 367         }
 368         if ((tp->t_mgt_cmd_data = allocb(8, BPRI_HI)) == NULL) {
 369                 sbp2_tgt_fini_bus(tp);
 370                 return (SBP2_ENOMEM);
 371         }
 372 
 373         return (SBP2_SUCCESS);
 374 }
 375 
 376 static void
 377 sbp2_tgt_fini_bus(sbp2_tgt_t *tp)
 378 {
 379         if (tp->t_mgt_status_fifo_buf.bb_hdl != NULL) {
 380                 SBP2_FREE_BUF(tp, &tp->t_mgt_status_fifo_buf);
 381         }
 382         if (tp->t_mgt_orb_buf.bb_hdl != NULL) {
 383                 SBP2_FREE_BUF(tp, &tp->t_mgt_orb_buf);
 384         }
 385         if (tp->t_mgt_login_resp_buf.bb_hdl != NULL) {
 386                 SBP2_FREE_BUF(tp, &tp->t_mgt_login_resp_buf);
 387         }
 388         if (tp->t_mgt_cmd) {
 389                 SBP2_FREE_CMD(tp, tp->t_mgt_cmd);
 390                 tp->t_mgt_cmd = NULL;
 391         }
 392         if (tp->t_mgt_cmd_data) {
 393                 freeb(tp->t_mgt_cmd_data);
 394                 tp->t_mgt_cmd_data = NULL;
 395         }
 396 }
 397 
 398 void
 399 sbp2_tgt_disconnect(sbp2_tgt_t *tp)
 400 {
 401         sbp2_tgt_fini_bus(tp);
 402 }
 403 
 404 int
 405 sbp2_tgt_reconnect(sbp2_tgt_t *tp)
 406 {
 407         return (sbp2_tgt_init_bus(tp));
 408 }
 409 
 410 /*
 411  * send mgt ORB and wait for status
 412  *
 413  * mgt agent should be acquired
 414  */
 415 static int
 416 sbp2_tgt_mgt_request(sbp2_tgt_t *tp, int *berr)
 417 {
 418         clock_t         until;
 419         int             ret;
 420 
 421         /*
 422          * When a ctl operation happens from HAL - this could be 0!
 423          * This will happen when a device is disconected and then
 424          * reconnected. Note  there are problems with not being able
 425          * to detach/eject a target before unplugging. That can cause
 426          * this to happen... This problem needs some work elseware!
 427          * This just prevents a needless panic. If we return failure
 428          * the target ultimatly will recover and is usable.
 429          */
 430         if (tp->t_mgt_cmd_data == 0) {
 431                 return (SBP2_FAILURE);
 432         }
 433 
 434         tp->t_mgt_status_rcvd = B_FALSE;
 435 
 436         /* write ORB address into MANAGEMENT_AGENT */
 437         SBP2_ADDR_SET(tp->t_mgt_cmd_data->b_rptr, tp->t_mgt_orb_buf.bb_baddr,
 438             0);
 439         tp->t_mgt_cmd_data->b_wptr = tp->t_mgt_cmd_data->b_rptr + 8;
 440 
 441         if ((ret = SBP2_WB(tp, tp->t_mgt_cmd, tp->t_mgt_agent,
 442             tp->t_mgt_cmd_data, 8, berr)) != SBP2_SUCCESS) {
 443                 return (ret);
 444         }
 445 
 446         /* wait for login response */
 447         mutex_enter(&tp->t_mutex);
 448         until = ddi_get_lbolt() + drv_usectohz(tp->t_mot * 1000);
 449         ret = 1;
 450 
 451         while (!tp->t_mgt_status_rcvd && (ret > 0)) {
 452                 ret = cv_timedwait(&tp->t_mgt_status_cv, &tp->t_mutex, until);
 453         }
 454 
 455         if (!tp->t_mgt_status_rcvd) {
 456                 ret = SBP2_ETIMEOUT;
 457         } else if ((tp->t_mgt_status.st_param & SBP2_ST_RESP) ==
 458             SBP2_ST_RESP_COMPLETE) {
 459                 ret = SBP2_SUCCESS;
 460         } else {
 461                 ret = SBP2_FAILURE;
 462         }
 463         mutex_exit(&tp->t_mutex);
 464 
 465         return (ret);
 466 }
 467 
 468 /*
 469  * Send task management request, one of:
 470  *
 471  *      ABORT TASK, ABORT TASK SET, LOGICAL UNIT RESET, TARGET RESET
 472  */
 473 static int
 474 sbp2_tgt_task_mgt_request(sbp2_tgt_t *tp, uint16_t id, int func, uint64_t orbp,
 475     int *berr)
 476 {
 477         sbp2_task_mgt_orb_t *torb;
 478         int             ret;
 479 
 480         sbp2_mgt_agent_acquire(tp);
 481 
 482         torb = (sbp2_task_mgt_orb_t *)tp->t_mgt_orb_buf.bb_kaddr;
 483         bzero(torb, sizeof (sbp2_task_mgt_orb_t));
 484         SBP2_ORBP_SET(torb->to_orb, orbp);
 485         torb->to_params = SBP2_SWAP16(func | SBP2_ORB_NOTIFY |
 486             SBP2_ORB_RQ_FMT_SBP2);
 487         torb->to_login_id = SBP2_SWAP16(id);
 488         SBP2_ADDR_SET(torb->to_status_fifo, tp->t_mgt_status_fifo_buf.bb_baddr,
 489             0);
 490 
 491         ret = sbp2_tgt_mgt_request(tp, berr);
 492 
 493         sbp2_mgt_agent_release(tp);
 494 
 495         return (ret);
 496 }
 497 
 498 int
 499 sbp2_tgt_reset(sbp2_tgt_t *tp, int *berr)
 500 {
 501         sbp2_lun_t      *lp = &tp->t_lun[0];
 502         int             ret;
 503 
 504         /* issue TARGET RESET */
 505         if ((ret = sbp2_tgt_task_mgt_request(tp, lp->l_login_resp.lr_login_id,
 506             SBP2_ORB_MGT_FUNC_TARGET_RESET, 0, berr)) != SBP2_SUCCESS) {
 507                 return (ret);
 508         }
 509 
 510         return (SBP2_SUCCESS);
 511 }
 512 
 513 int
 514 sbp2_tgt_get_cfgrom(sbp2_tgt_t *tp, sbp2_cfgrom_t **crpp)
 515 {
 516         *crpp = &tp->t_cfgrom;
 517         return (SBP2_SUCCESS);
 518 }
 519 
 520 int
 521 sbp2_tgt_get_lun_cnt(sbp2_tgt_t *tp)
 522 {
 523         return (tp->t_nluns);
 524 }
 525 
 526 sbp2_lun_t *
 527 sbp2_tgt_get_lun(sbp2_tgt_t *tp, int num)
 528 {
 529         if (num < tp->t_nluns) {
 530                 return (&tp->t_lun[num]);
 531         } else {
 532                 return (NULL);
 533         }
 534 }
 535 
 536 /*
 537  *
 538  * --- lun routines
 539  *
 540  */
 541 int
 542 sbp2_lun_reset(sbp2_lun_t *lp, int *berr)
 543 {
 544         sbp2_tgt_t      *tp = lp->l_tgt;
 545         sbp2_ses_t      *sp = lp->l_ses;
 546         sbp2_task_t     *task = NULL;
 547         int             ret;
 548 
 549         /* issue LOGICAL UNIT RESET */
 550         if ((ret = sbp2_tgt_task_mgt_request(tp, lp->l_login_resp.lr_login_id,
 551             SBP2_ORB_MGT_FUNC_LUN_RESET, 0, berr)) != SBP2_SUCCESS) {
 552                 return (ret);
 553         }
 554 
 555         /* mark all pending tasks reset and notify the driver */
 556         mutex_enter(&sp->s_task_mutex);
 557         for (task = sp->s_task_head; task != NULL; task = task->ts_next) {
 558                 if (task->ts_state < SBP2_TASK_COMP) {
 559                         task->ts_error = SBP2_TASK_ERR_LUN_RESET;
 560                         task->ts_state = SBP2_TASK_COMP;
 561                 }
 562         }
 563         mutex_exit(&sp->s_task_mutex);
 564 
 565         sp->s_status_cb(sp->s_status_cb_arg, NULL);
 566 
 567         return (SBP2_SUCCESS);
 568 }
 569 
 570 int
 571 sbp2_lun_login(sbp2_lun_t *lp, sbp2_ses_t **spp,
 572     void (*cb)(void *, sbp2_task_t *), void *cb_arg, int *berr)
 573 {
 574         sbp2_tgt_t      *tp = lp->l_tgt;
 575         sbp2_ses_t      *sp;
 576         sbp2_login_orb_t *lorb;
 577         int             ret;
 578 
 579         if (cb == NULL) {
 580                 return (SBP2_EINVAL);
 581         }
 582 
 583         /* multiple sessions not supported yet */
 584         if (lp->l_ses != NULL) {
 585                 return (SBP2_EALREADY);
 586         }
 587 
 588         if ((ret = sbp2_ses_init(&sp, lp, cb, cb_arg)) != SBP2_SUCCESS) {
 589                 return (ret);
 590         }
 591         lp->l_ses = sp;
 592 
 593         sbp2_mgt_agent_acquire(tp);
 594 
 595         /* prepare login ORB */
 596         mutex_enter(&tp->t_mutex);
 597         lorb = (sbp2_login_orb_t *)tp->t_mgt_orb_buf.bb_kaddr;
 598         bzero(lorb, sizeof (sbp2_login_orb_t));
 599         SBP2_ADDR_SET(lorb->lo_resp, tp->t_mgt_login_resp_buf.bb_baddr, 0);
 600         lorb->lo_params = SBP2_SWAP16(SBP2_ORB_MGT_FUNC_LOGIN |
 601             SBP2_ORB_LOGIN_EXCL | SBP2_ORB_NOTIFY | SBP2_ORB_RQ_FMT_SBP2);
 602         lorb->lo_lun = SBP2_SWAP16(lp->l_lun);
 603         lorb->lo_resp_len = SBP2_SWAP16(tp->t_mgt_login_resp_buf.bb_len);
 604         SBP2_ADDR_SET(lorb->lo_status_fifo, sp->s_status_fifo_buf.bb_baddr, 0);
 605 
 606         bzero(tp->t_mgt_login_resp_buf.bb_kaddr, sizeof (sbp2_login_resp_t));
 607 
 608         lp->l_logged_in = B_FALSE;
 609         mutex_exit(&tp->t_mutex);
 610 
 611         /* send request */
 612         if ((ret = sbp2_tgt_mgt_request(tp, berr)) != SBP2_SUCCESS) {
 613                 sbp2_mgt_agent_release(tp);
 614                 sbp2_ses_fini(lp->l_ses);
 615                 lp->l_ses = NULL;
 616                 return (ret);
 617         }
 618 
 619         /* retrieve response data (XXX sanity checks?) */
 620         mutex_enter(&tp->t_mutex);
 621         (void) SBP2_SYNC_BUF(tp, &tp->t_mgt_login_resp_buf, 0, 0,
 622             DDI_DMA_SYNC_FORKERNEL);
 623         bcopy(tp->t_mgt_login_resp_buf.bb_kaddr, &lp->l_login_resp,
 624             sizeof (sbp2_login_resp_t));
 625 
 626         /* convert from BE to native endianness */
 627         SBP2_SWAP16_1(lp->l_login_resp.lr_len);
 628         SBP2_SWAP16_1(lp->l_login_resp.lr_login_id);
 629         SBP2_SWAP32_2(lp->l_login_resp.lr_cmd_agent);
 630         SBP2_SWAP16_1(lp->l_login_resp.lr_reconnect_hold);
 631         lp->l_login_resp.lr_reconnect_hold++;
 632 
 633         sp->s_agent_offset = SBP2_ADDR2UINT64(lp->l_login_resp.lr_cmd_agent);
 634 
 635         lp->l_logged_in = B_TRUE;
 636         mutex_exit(&tp->t_mutex);
 637 
 638         sbp2_mgt_agent_release(tp);
 639 
 640         if ((ret = sbp2_agent_init(&sp->s_agent, sp->s_agent_offset, tp)) !=
 641             SBP2_SUCCESS) {
 642                 sbp2_ses_fini(sp);
 643                 lp->l_ses = NULL;
 644                 return (ret);
 645         }
 646 
 647         *spp = lp->l_ses;
 648         return (SBP2_SUCCESS);
 649 }
 650 
 651 /*ARGSUSED*/
 652 int
 653 sbp2_lun_logout(sbp2_lun_t *lp, sbp2_ses_t **sp, int *berr, boolean_t phys)
 654 {
 655         sbp2_tgt_t      *tp = lp->l_tgt;
 656 
 657         ASSERT(*sp == lp->l_ses);
 658 
 659         mutex_enter(&tp->t_mutex);
 660         if (lp->l_logged_in) {
 661                 lp->l_logged_in = B_FALSE;
 662                 /* do physical LOGOUT if requested */
 663                 if (phys) {
 664                         mutex_exit(&tp->t_mutex);
 665                         sbp2_lun_logout_orb(lp, tp, berr);
 666                         mutex_enter(&tp->t_mutex);
 667                 }
 668         }
 669 
 670         sbp2_agent_fini(&lp->l_ses->s_agent);
 671         sbp2_ses_fini(lp->l_ses);
 672         lp->l_ses = NULL;
 673         *sp = NULL;
 674         mutex_exit(&tp->t_mutex);
 675 
 676         return (SBP2_SUCCESS);
 677 }
 678 
 679 /*
 680  * Issue LOGOUT mgt orb and wait for response. We are not interested in
 681  * the success at the time, since the device may be disconnected or hung,
 682  * just trying to make the best effort.
 683  */
 684 static void
 685 sbp2_lun_logout_orb(sbp2_lun_t *lp, sbp2_tgt_t *tp, int *berr)
 686 {
 687         sbp2_logout_orb_t *lorb;
 688 
 689         sbp2_mgt_agent_acquire(tp);
 690 
 691         /* prepare logout ORB */
 692         lorb = (sbp2_logout_orb_t *)tp->t_mgt_orb_buf.bb_kaddr;
 693         bzero(lorb, sizeof (sbp2_logout_orb_t));
 694         lorb->lo_params = SBP2_SWAP16(SBP2_ORB_MGT_FUNC_LOGOUT |
 695             SBP2_ORB_NOTIFY | SBP2_ORB_RQ_FMT_SBP2);
 696         lorb->lo_login_id = SBP2_SWAP16(lp->l_login_resp.lr_login_id);
 697         SBP2_ADDR_SET(lorb->lo_status_fifo, tp->t_mgt_status_fifo_buf.bb_baddr,
 698             0);
 699 
 700         /* send request */
 701         (void) sbp2_tgt_mgt_request(tp, berr);
 702 
 703         sbp2_mgt_agent_release(tp);
 704 }
 705 
 706 static boolean_t
 707 sbp2_lun_accepting_tasks(sbp2_lun_t *lp)
 708 {
 709         sbp2_tgt_t      *tp = lp->l_tgt;
 710         boolean_t       ret;
 711 
 712         mutex_enter(&tp->t_mutex);
 713         ret = ((lp->l_ses != NULL) && lp->l_logged_in && !lp->l_reconnecting);
 714         mutex_exit(&tp->t_mutex);
 715         return (ret);
 716 }
 717 
 718 /*
 719  *
 720  * --- session routines
 721  *
 722  */
 723 static int
 724 sbp2_ses_init(sbp2_ses_t **spp, sbp2_lun_t *lp,
 725     void (*cb)(void *, sbp2_task_t *), void *cb_arg)
 726 {
 727         sbp2_tgt_t      *tp = lp->l_tgt;
 728         sbp2_ses_t      *sp;
 729         int             ret;
 730 
 731         sp = kmem_zalloc(sizeof (sbp2_ses_t), KM_SLEEP);
 732 
 733         sp->s_tgt = tp;
 734         sp->s_lun = lp;
 735         sp->s_status_cb = cb;
 736         sp->s_status_cb_arg = cb_arg;
 737 
 738         mutex_init(&sp->s_mutex, NULL, MUTEX_DRIVER,
 739             SBP2_GET_IBLOCK_COOKIE(tp));
 740         mutex_init(&sp->s_task_mutex, NULL, MUTEX_DRIVER,
 741             SBP2_GET_IBLOCK_COOKIE(tp));
 742 
 743         /*
 744          * status FIFO for block requests
 745          */
 746         sp->s_status_fifo_buf.bb_len = sizeof (sbp2_status_t);
 747         sp->s_status_fifo_buf.bb_flags = SBP2_BUS_BUF_WR_POSTED;
 748         sp->s_status_fifo_buf.bb_wb_cb = sbp2_status_fifo_wb_cb;
 749         sp->s_status_fifo_buf.bb_sbp2_priv = sp;
 750         if ((ret = SBP2_ALLOC_BUF(tp, &sp->s_status_fifo_buf)) !=
 751             SBP2_SUCCESS) {
 752                 sbp2_ses_fini(sp);
 753                 return (ret);
 754         }
 755 
 756         *spp = sp;
 757         return (SBP2_SUCCESS);
 758 }
 759 
 760 
 761 static void
 762 sbp2_ses_fini(sbp2_ses_t *sp)
 763 {
 764         sbp2_tgt_t      *tp = sp->s_lun->l_tgt;
 765 
 766         if (sp->s_status_fifo_buf.bb_hdl != NULL) {
 767                 SBP2_FREE_BUF(tp, &sp->s_status_fifo_buf);
 768         }
 769 
 770         mutex_destroy(&sp->s_task_mutex);
 771         mutex_destroy(&sp->s_mutex);
 772 
 773         kmem_free(sp, sizeof (sbp2_ses_t));
 774 }
 775 
 776 int
 777 sbp2_ses_reconnect(sbp2_ses_t *sp, int *berr, uint16_t nodeID)
 778 {
 779         sbp2_tgt_t      *tp = sp->s_tgt;
 780         sbp2_lun_t      *lp = sp->s_lun;
 781         int             ret;
 782 
 783         /* prevent new tasks from being submitted */
 784         mutex_enter(&tp->t_mutex);
 785         lp->l_reconnecting = B_TRUE;
 786         mutex_exit(&tp->t_mutex);
 787 
 788         /*
 789          * From 10.5 Task management event matrix:
 790          *      Immediately upon detection of a bus reset, all command
 791          *      block fetch agents transition to the reset state and
 792          *      their associated task sets are cleared without
 793          *      the return of completion status.
 794          *
 795          * Reset pending tasks so we can retry them later.
 796          */
 797         sbp2_ses_reset_pending_tasks(sp, nodeID);
 798 
 799         ret = sbp2_ses_reconnect_orb(sp, berr);
 800 
 801         mutex_enter(&tp->t_mutex);
 802         lp->l_reconnecting = B_FALSE;
 803         mutex_exit(&tp->t_mutex);
 804 
 805         return (ret);
 806 }
 807 
 808 /*
 809  * Send reconnect ORB. If operation fails, set lp->l_logged_in = B_FALSE.
 810  */
 811 static int
 812 sbp2_ses_reconnect_orb(sbp2_ses_t *sp, int *berr)
 813 {
 814         sbp2_tgt_t      *tp = sp->s_tgt;
 815         sbp2_lun_t      *lp = sp->s_lun;
 816         sbp2_agent_t    *ap = &sp->s_agent;
 817         sbp2_reconnect_orb_t *rorb;
 818         int             ret;
 819 
 820         sbp2_mgt_agent_acquire(tp);
 821 
 822         /* prepare login ORB */
 823         rorb = (sbp2_reconnect_orb_t *)tp->t_mgt_orb_buf.bb_kaddr;
 824         bzero(rorb, sizeof (sbp2_reconnect_orb_t));
 825         rorb->ro_params = SBP2_SWAP16(SBP2_ORB_MGT_FUNC_RECONNECT |
 826             SBP2_ORB_NOTIFY | SBP2_ORB_RQ_FMT_SBP2);
 827         rorb->ro_login_id = SBP2_SWAP16(lp->l_login_resp.lr_login_id);
 828         SBP2_ADDR_SET(rorb->ro_status_fifo, tp->t_mgt_status_fifo_buf.bb_baddr,
 829             0);
 830 
 831         /* send request */
 832         if ((ret = sbp2_tgt_mgt_request(tp, berr)) != SBP2_SUCCESS) {
 833                 mutex_enter(&tp->t_mutex);
 834                 lp->l_logged_in = B_FALSE;
 835                 mutex_exit(&tp->t_mutex);
 836         } else {
 837                 /* after successful reset fetch agent is in RESET state */
 838                 mutex_enter(&ap->a_mutex);
 839                 ap->a_state = SBP2_AGENT_STATE_RESET;
 840                 mutex_exit(&ap->a_mutex);
 841         }
 842 
 843         sbp2_mgt_agent_release(tp);
 844 
 845         return (ret);
 846 }
 847 
 848 
 849 static sbp2_task_t *
 850 sbp2_ses_orbp2task(sbp2_ses_t *sp, uint64_t orbp)
 851 {
 852         sbp2_task_t     *task;
 853 
 854         mutex_enter(&sp->s_task_mutex);
 855         for (task = sp->s_task_head; task != NULL; task = task->ts_next) {
 856                 if (task->ts_buf->bb_baddr == orbp) {
 857                         break;
 858                 }
 859         }
 860         mutex_exit(&sp->s_task_mutex);
 861         return (task);
 862 }
 863 
 864 /*
 865  * This is where tasks (command ORB's) are signalled to the target.
 866  * 'task' argument is allowed to be NULL, in which case the task will be
 867  * taken from the current task list.
 868  *
 869  * Tasks are signalled one at a time by writing into ORB_POINTER register.
 870  * While SBP-2 allows dynamic task list updates and using DOORBELL register,
 871  * some devices have bugs that prevent using this strategy: e.g. some LaCie
 872  * HDD's can corrupt data. Data integrity is more important than performance.
 873  */
 874 int
 875 sbp2_ses_submit_task(sbp2_ses_t *sp, sbp2_task_t *new_task)
 876 {
 877         sbp2_agent_t    *ap = &sp->s_agent;
 878         sbp2_tgt_t      *tp = sp->s_tgt;
 879         sbp2_task_t     *task;          /* task actually being submitted */
 880         boolean_t       callback;
 881         timeout_id_t    timeout_id;
 882         int             ret;
 883 
 884         if (!sbp2_lun_accepting_tasks(sp->s_lun)) {
 885                 return (SBP2_ENODEV);
 886         }
 887 
 888         sbp2_agent_acquire(ap); /* serialize */
 889 
 890         mutex_enter(&ap->a_mutex);
 891 
 892         /* if task provided, append it to the list */
 893         if (new_task != NULL) {
 894                 ASSERT(new_task->ts_state == SBP2_TASK_INIT);
 895                 sbp2_ses_append_task(sp, new_task);
 896         }
 897 
 898         /* if there is already a task in flight, exit */
 899         if ((ap->a_active_task != NULL) &&
 900             (ap->a_active_task->ts_state == SBP2_TASK_PEND)) {
 901                 mutex_exit(&ap->a_mutex);
 902                 sbp2_agent_release(ap);
 903                 return (SBP2_SUCCESS);
 904         }
 905 
 906         /*
 907          * cannot submit tasks from interrupt context,
 908          * upper layer driver is responsible to call nudge
 909          */
 910         if (servicing_interrupt()) {
 911                 mutex_exit(&ap->a_mutex);
 912                 sbp2_agent_release(ap);
 913                 return (SBP2_ECONTEXT);
 914         }
 915 
 916         /* no active task, grab the first one on the list in INIT state */
 917         ap->a_active_task = sbp2_ses_find_task_state(sp, SBP2_TASK_INIT);
 918         if (ap->a_active_task == NULL) {
 919                 mutex_exit(&ap->a_mutex);
 920                 sbp2_agent_release(ap);
 921                 return (SBP2_SUCCESS);
 922         }
 923         task = ap->a_active_task;
 924         task->ts_ses = sp;
 925         task->ts_state = SBP2_TASK_PEND;
 926 
 927         /* can't work with a dead agent */
 928         if (sbp2_agent_keepalive(ap, &task->ts_bus_error) != SBP2_SUCCESS) {
 929                 task->ts_error = SBP2_TASK_ERR_DEAD;
 930                 goto error;
 931         }
 932 
 933         /*
 934          * In theory, we should schedule task timeout after it's been submitted.
 935          * However, some fast tasks complete even before timeout is scheduled.
 936          * To avoid additional complications in the code, schedule timeout now.
 937          */
 938         ASSERT(task->ts_timeout_id == 0);
 939         task->ts_time_start = gethrtime();
 940         if (task->ts_timeout > 0) {
 941                 task->ts_timeout_id = timeout(sbp2_task_timeout, task,
 942                     task->ts_timeout * drv_usectohz(1000000));
 943         }
 944 
 945         /* notify fetch agent */
 946         ap->a_state = SBP2_AGENT_STATE_ACTIVE;
 947         mutex_exit(&ap->a_mutex);
 948         ret = sbp2_agent_write_orbp(ap, task->ts_buf->bb_baddr,
 949             &task->ts_bus_error);
 950         tp->t_stat.stat_submit_orbp++;
 951         mutex_enter(&ap->a_mutex);
 952 
 953         if (ret != SBP2_SUCCESS) {
 954                 ap->a_state = SBP2_AGENT_STATE_DEAD;
 955                 tp->t_stat.stat_status_dead++;
 956 
 957                 if (task->ts_timeout_id != 0) {
 958                         timeout_id = task->ts_timeout_id;
 959                         task->ts_timeout_id = 0;
 960                         (void) untimeout(timeout_id);
 961                 }
 962                 task->ts_error = SBP2_TASK_ERR_BUS;
 963                 goto error;
 964         }
 965 
 966         mutex_exit(&ap->a_mutex);
 967 
 968         sbp2_agent_release(ap);
 969         return (SBP2_SUCCESS);
 970 
 971 error:
 972         /*
 973          * Return immediate error if failed task is the one being submitted,
 974          * otherwise use callback.
 975          */
 976         callback = (ap->a_active_task != new_task);
 977         ASSERT(task == ap->a_active_task);
 978         ap->a_active_task = NULL;
 979         mutex_exit(&ap->a_mutex);
 980         sbp2_agent_release(ap);
 981 
 982         /*
 983          * Remove task from the list. It is important not to change task state
 984          * to SBP2_TASK_COMP while it's still on the list, to avoid race with
 985          * upper layer driver (e.g. scsa1394).
 986          */
 987         ret = sbp2_ses_remove_task(sp, task);
 988         ASSERT(ret == SBP2_SUCCESS);
 989         task->ts_state = SBP2_TASK_COMP;
 990 
 991         if (callback) {
 992                 sp->s_status_cb(sp->s_status_cb_arg, task);
 993                 return (SBP2_SUCCESS);
 994         } else {
 995                 /* upper layer driver is responsible to call nudge */
 996                 return (SBP2_FAILURE);
 997         }
 998 }
 999 
1000 void
1001 sbp2_ses_nudge(sbp2_ses_t *sp)
1002 {
1003         (void) sbp2_ses_submit_task(sp, NULL);
1004 }
1005 
1006 /*
1007  * append task to the task list
1008  */
1009 static void
1010 sbp2_ses_append_task(sbp2_ses_t *sp, sbp2_task_t *task)
1011 {
1012         sbp2_tgt_t      *tp = sp->s_tgt;
1013 
1014         mutex_enter(&sp->s_task_mutex);
1015         if (sp->s_task_head == NULL) {
1016                 ASSERT(sp->s_task_tail == NULL);
1017                 ASSERT(sp->s_task_cnt == 0);
1018                 task->ts_prev = task->ts_next = NULL;
1019                 sp->s_task_head = sp->s_task_tail = task;
1020         } else {
1021                 ASSERT(sp->s_task_cnt > 0);
1022                 task->ts_next = NULL;
1023                 task->ts_prev = sp->s_task_tail;
1024                 sp->s_task_tail->ts_next = task;
1025                 sp->s_task_tail = task;
1026         }
1027         ASSERT(task != task->ts_prev);
1028         ASSERT(task != task->ts_next);
1029 
1030         sp->s_task_cnt++;
1031         if (sp->s_task_cnt > tp->t_stat.stat_task_max) {
1032                 tp->t_stat.stat_task_max = sp->s_task_cnt;
1033         }
1034         mutex_exit(&sp->s_task_mutex);
1035 }
1036 
1037 /*
1038  * remove task from the task list
1039  */
1040 static int
1041 sbp2_ses_remove_task_locked(sbp2_ses_t *sp, sbp2_task_t *task)
1042 {
1043         sp->s_task_cnt--;
1044         if (task == sp->s_task_head) {                       /* first */
1045                 ASSERT(task->ts_prev == NULL);
1046                 if (task->ts_next == NULL) {         /*   and last */
1047                         ASSERT(sp->s_task_cnt == 0);
1048                         sp->s_task_head = sp->s_task_tail = NULL;
1049                 } else {                                /*   but not last */
1050                         sp->s_task_head = task->ts_next;
1051                         sp->s_task_head->ts_prev = NULL;
1052                 }
1053         } else if (task == sp->s_task_tail) {                /* last but not first */
1054                 ASSERT(task->ts_next == NULL);
1055                 sp->s_task_tail = task->ts_prev;
1056                 sp->s_task_tail->ts_next = NULL;
1057         } else {                                        /* in the middle */
1058                 task->ts_prev->ts_next = task->ts_next;
1059                 task->ts_next->ts_prev = task->ts_prev;
1060         }
1061         task->ts_prev = task->ts_next = NULL;
1062         ASSERT(sp->s_task_cnt >= 0);
1063 
1064         return (SBP2_SUCCESS);
1065 }
1066 
1067 int
1068 sbp2_ses_remove_task(sbp2_ses_t *sp, sbp2_task_t *task)
1069 {
1070         int     ret;
1071 
1072         mutex_enter(&sp->s_task_mutex);
1073         ret = sbp2_ses_remove_task_locked(sp, task);
1074         mutex_exit(&sp->s_task_mutex);
1075 
1076         return (ret);
1077 }
1078 
1079 /*
1080  * Return first task on the list in specified state.
1081  */
1082 sbp2_task_t *
1083 sbp2_ses_find_task_state(sbp2_ses_t *sp, sbp2_task_state_t state)
1084 {
1085         sbp2_task_t     *task = NULL;
1086 
1087         mutex_enter(&sp->s_task_mutex);
1088         for (task = sp->s_task_head; task != NULL; task = task->ts_next) {
1089                 if (task->ts_state == state) {
1090                         break;
1091                 }
1092         }
1093         mutex_exit(&sp->s_task_mutex);
1094 
1095         return (task);
1096 }
1097 
1098 /*
1099  * Remove first task on the list. Returns pointer to the removed task or NULL.
1100  */
1101 sbp2_task_t *
1102 sbp2_ses_remove_first_task(sbp2_ses_t *sp)
1103 {
1104         sbp2_task_t     *task = NULL;
1105 
1106         mutex_enter(&sp->s_task_mutex);
1107         task = sp->s_task_head;
1108         if (task != NULL) {
1109                 (void) sbp2_ses_remove_task_locked(sp, task);
1110         }
1111         mutex_exit(&sp->s_task_mutex);
1112 
1113         return (task);
1114 }
1115 
1116 /*
1117  * Remove first task on the list only if it's in specified state.
1118  * Returns pointer to the removed task or NULL.
1119  */
1120 sbp2_task_t *
1121 sbp2_ses_remove_first_task_state(sbp2_ses_t *sp, sbp2_task_state_t state)
1122 {
1123         sbp2_task_t     *task = NULL;
1124 
1125         mutex_enter(&sp->s_task_mutex);
1126         if ((sp->s_task_head != NULL) && (sp->s_task_head->ts_state == state)) {
1127                 task = sp->s_task_head;
1128                 (void) sbp2_ses_remove_task_locked(sp, task);
1129         }
1130         mutex_exit(&sp->s_task_mutex);
1131 
1132         return (task);
1133 }
1134 
1135 /*
1136  * Remove first task on the list. If there's timeout, untimeout it.
1137  * Returns pointer to the removed task or NULL.
1138  */
1139 sbp2_task_t *
1140 sbp2_ses_cancel_first_task(sbp2_ses_t *sp)
1141 {
1142         sbp2_task_t     *task = NULL;
1143         timeout_id_t    timeout_id;
1144 
1145         mutex_enter(&sp->s_task_mutex);
1146         task = sp->s_task_head;
1147         if (task != NULL) {
1148                 (void) sbp2_ses_remove_task_locked(sp, task);
1149         }
1150         mutex_exit(&sp->s_task_mutex);
1151 
1152         if ((task != NULL) && ((timeout_id = task->ts_timeout_id) != 0)) {
1153                 task->ts_timeout_id = 0;
1154                 (void) untimeout(timeout_id);
1155         }
1156 
1157         return (task);
1158 }
1159 
1160 /*
1161  * Reset pending tasks on the list to their initial state.
1162  */
1163 static void
1164 sbp2_ses_reset_pending_tasks(sbp2_ses_t *sp, uint16_t nodeID)
1165 {
1166         sbp2_agent_t    *ap = &sp->s_agent;
1167         sbp2_task_t     *task = NULL;
1168         timeout_id_t    timeout_id;
1169         sbp2_cmd_orb_t  *orb;
1170 
1171         mutex_enter(&sp->s_task_mutex);
1172         for (task = sp->s_task_head; task != NULL; task = task->ts_next) {
1173                 task->ts_state = SBP2_TASK_INIT;
1174 
1175                 /* cancel timeout */
1176                 if ((timeout_id = task->ts_timeout_id) != 0) {
1177                         task->ts_timeout_id = 0;
1178                         (void) untimeout(timeout_id);
1179                 }
1180 
1181                 /* update ORB nodeID */
1182                 orb = (sbp2_cmd_orb_t *)sbp2_task_orb_kaddr(task);
1183                 *(uint16_t *)orb->co_data_descr = SBP2_SWAP16(nodeID);
1184                 sbp2_task_orb_sync(sp->s_lun, task, DDI_DMA_SYNC_FORDEV);
1185         }
1186         mutex_exit(&sp->s_task_mutex);
1187 
1188         mutex_enter(&ap->a_mutex);
1189         ap->a_active_task = NULL;
1190         mutex_exit(&ap->a_mutex);
1191 }
1192 
1193 int
1194 sbp2_ses_agent_reset(sbp2_ses_t *sp, int *berr)
1195 {
1196         return (sbp2_agent_reset(&sp->s_agent, berr));
1197 }
1198 
1199 int
1200 sbp2_ses_abort_task(sbp2_ses_t *sp, sbp2_task_t *task, int *berr)
1201 {
1202         sbp2_tgt_t      *tp = sp->s_tgt;
1203         sbp2_lun_t      *lp = sp->s_lun;
1204         uint16_t        params;
1205         sbp2_cmd_orb_t  *orb = (sbp2_cmd_orb_t *)task->ts_buf->bb_kaddr;
1206         int             ret = SBP2_SUCCESS;
1207 
1208         /* mark ORB as dummy ORB */
1209         params = (orb->co_params & ~SBP2_ORB_RQ_FMT) | SBP2_ORB_RQ_FMT_DUMMY;
1210         orb->co_params = params;
1211         (void) SBP2_SYNC_BUF(tp, task->ts_buf, 0, 0, DDI_DMA_SYNC_FORDEV);
1212 
1213         ret = sbp2_tgt_task_mgt_request(tp, lp->l_login_resp.lr_login_id,
1214             SBP2_ORB_MGT_FUNC_ABORT_TASK, task->ts_buf->bb_baddr, berr);
1215 
1216         return (ret);
1217 }
1218 
1219 
1220 int
1221 sbp2_ses_abort_task_set(sbp2_ses_t *sp, int *berr)
1222 {
1223         sbp2_tgt_t      *tp = sp->s_tgt;
1224         sbp2_lun_t      *lp = sp->s_lun;
1225         int             ret;
1226 
1227         ret = sbp2_tgt_task_mgt_request(tp, lp->l_login_resp.lr_login_id,
1228             SBP2_ORB_MGT_FUNC_ABORT_TASK_SET, 0, berr);
1229 
1230         return (ret);
1231 }
1232 
1233 
1234 /*
1235  *
1236  * ORB functions
1237  *
1238  * allocate ORB resources
1239  *
1240  * we maintain a freelist of ORB's for faster allocation
1241  */
1242 /*ARGSUSED*/
1243 static sbp2_bus_buf_t *
1244 sbp2_orb_freelist_get(sbp2_lun_t *lp, sbp2_task_t *task, int len)
1245 {
1246         sbp2_buf_list_t *bl = &lp->l_orb_freelist;
1247         sbp2_bus_buf_t  *buf = NULL;
1248 
1249         mutex_enter(&bl->bl_mutex);
1250         if ((bl->bl_head != NULL) && (bl->bl_head->bb_len == len)) {
1251                 buf = bl->bl_head;
1252                 bl->bl_head = buf->bb_next;
1253                 if (bl->bl_tail == buf) {    /* last one? */
1254                         ASSERT(bl->bl_head == NULL);
1255                         bl->bl_tail = NULL;
1256                 }
1257                 bl->bl_len--;
1258                 buf->bb_next = NULL;
1259         }
1260         mutex_exit(&bl->bl_mutex);
1261 
1262         return (buf);
1263 }
1264 
1265 static int
1266 sbp2_orb_freelist_put(sbp2_lun_t *lp, sbp2_bus_buf_t *buf)
1267 {
1268         sbp2_buf_list_t *bl = &lp->l_orb_freelist;
1269         int             ret;
1270 
1271         mutex_enter(&bl->bl_mutex);
1272         if (bl->bl_len < SBP2_ORB_FREELIST_MAX) {
1273                 if (bl->bl_head == NULL) {
1274                         ASSERT(bl->bl_tail == NULL);
1275                         bl->bl_head = bl->bl_tail = buf;
1276                 } else {
1277                         bl->bl_tail->bb_next = buf;
1278                         bl->bl_tail = buf;
1279                 }
1280                 buf->bb_next = NULL;
1281                 bl->bl_len++;
1282                 ret = SBP2_SUCCESS;
1283         } else {
1284                 ret = SBP2_FAILURE;
1285         }
1286         mutex_exit(&bl->bl_mutex);
1287 
1288         return (ret);
1289 }
1290 
1291 static void
1292 sbp2_orb_freelist_destroy(sbp2_lun_t *lp)
1293 {
1294         sbp2_tgt_t      *tp = lp->l_tgt;
1295         sbp2_buf_list_t *bl = &lp->l_orb_freelist;
1296         sbp2_bus_buf_t  *buf, *buf_next;
1297 
1298         mutex_enter(&bl->bl_mutex);
1299         for (buf = bl->bl_head; buf != NULL; ) {
1300                 SBP2_FREE_BUF(tp, buf);
1301                 buf_next = buf->bb_next;
1302                 kmem_free(buf, sizeof (sbp2_bus_buf_t));
1303                 buf = buf_next;
1304         }
1305         bl->bl_head = bl->bl_tail = NULL;
1306         mutex_exit(&bl->bl_mutex);
1307 }
1308 
1309 int
1310 sbp2_task_orb_alloc(sbp2_lun_t *lp, sbp2_task_t *task, int len)
1311 {
1312         sbp2_tgt_t      *tp = lp->l_tgt;
1313         int             buf_len;
1314         int             ret;
1315 
1316         buf_len = SBP2_ORB_SIZE_ROUNDUP(tp, len);
1317 
1318         /* try freelist first */
1319         if ((task->ts_buf = sbp2_orb_freelist_get(lp, task, buf_len)) != NULL) {
1320                 return (SBP2_SUCCESS);
1321         }
1322 
1323         /* if no free buffers, allocate new */
1324         task->ts_buf = kmem_zalloc(sizeof (sbp2_bus_buf_t), KM_SLEEP);
1325         task->ts_buf->bb_len = buf_len;
1326         task->ts_buf->bb_flags = SBP2_BUS_BUF_DMA | SBP2_BUS_BUF_RD;
1327         if ((ret = SBP2_ALLOC_BUF(tp, task->ts_buf)) != SBP2_SUCCESS) {
1328                 kmem_free(task->ts_buf, sizeof (sbp2_bus_buf_t));
1329                 task->ts_buf = NULL;
1330         }
1331 
1332         return (ret);
1333 }
1334 
1335 void
1336 sbp2_task_orb_free(sbp2_lun_t *lp, sbp2_task_t *task)
1337 {
1338         sbp2_tgt_t      *tp = lp->l_tgt;
1339 
1340         if (task->ts_buf != NULL) {
1341                 if (sbp2_orb_freelist_put(lp, task->ts_buf) != SBP2_SUCCESS) {
1342                         SBP2_FREE_BUF(tp, task->ts_buf);
1343                         kmem_free(task->ts_buf, sizeof (sbp2_bus_buf_t));
1344                 }
1345                 task->ts_buf = NULL;
1346         }
1347 }
1348 
1349 void *
1350 sbp2_task_orb_kaddr(sbp2_task_t *task)
1351 {
1352         return (task->ts_buf->bb_kaddr);
1353 }
1354 
1355 void
1356 sbp2_task_orb_sync(sbp2_lun_t *lp, sbp2_task_t *task, int flags)
1357 {
1358         (void) SBP2_SYNC_BUF(lp->l_tgt, task->ts_buf, 0, 0, flags);
1359 }
1360 
1361 /*
1362  *
1363  * --- fetch agent routines
1364  *
1365  */
1366 static int
1367 sbp2_agent_init(sbp2_agent_t *ap, uint64_t offset, sbp2_tgt_t *tp)
1368 {
1369         int     ret;
1370 
1371         /* paranoia */
1372         if (offset == 0) {
1373                 return (SBP2_FAILURE);
1374         }
1375 
1376         ap->a_tgt = tp;
1377 
1378         ap->a_reg_agent_state = offset + SBP2_AGENT_STATE_OFFSET;
1379         ap->a_reg_agent_reset = offset + SBP2_AGENT_RESET_OFFSET;
1380         ap->a_reg_orbp = offset + SBP2_ORB_POINTER_OFFSET;
1381         ap->a_reg_doorbell = offset + SBP2_DOORBELL_OFFSET;
1382         ap->a_reg_unsol_status_enable = offset +
1383             SBP2_UNSOLICITED_STATUS_ENABLE_OFFSET;
1384 
1385         /*
1386          * allocate bus commands
1387          */
1388         if ((ret = SBP2_ALLOC_CMD(tp, &ap->a_cmd, 0)) != SBP2_SUCCESS) {
1389                 return (ret);
1390         }
1391         ap->a_cmd_data = allocb(sizeof (sbp2_orbp_t), BPRI_HI);
1392         if (ap->a_cmd_data == NULL) {
1393                 sbp2_agent_fini(ap);
1394                 return (SBP2_ENOMEM);
1395         }
1396 
1397         mutex_init(&ap->a_mutex, NULL, MUTEX_DRIVER,
1398             SBP2_GET_IBLOCK_COOKIE(tp));
1399         cv_init(&ap->a_cv, NULL, CV_DRIVER, NULL);
1400 
1401 #ifndef __lock_lint
1402         ap->a_state = SBP2_AGENT_STATE_RESET;
1403 #endif
1404 
1405         return (SBP2_SUCCESS);
1406 }
1407 
1408 
1409 static void
1410 sbp2_agent_fini(sbp2_agent_t *ap)
1411 {
1412         sbp2_tgt_t      *tp = ap->a_tgt;
1413 
1414         /* free bus commands */
1415         if (ap->a_cmd != NULL) {
1416                 SBP2_FREE_CMD(tp, ap->a_cmd);
1417         }
1418         if (ap->a_cmd_data != NULL) {
1419                 freeb(ap->a_cmd_data);
1420         }
1421         cv_destroy(&ap->a_cv);
1422         mutex_destroy(&ap->a_mutex);
1423 }
1424 
1425 
1426 static void
1427 sbp2_agent_acquire_locked(sbp2_agent_t *ap)
1428 {
1429         while (ap->a_acquired) {
1430                 cv_wait(&ap->a_cv, &ap->a_mutex);
1431         }
1432         ap->a_acquired = B_TRUE;
1433 }
1434 
1435 
1436 static void
1437 sbp2_agent_release_locked(sbp2_agent_t *ap)
1438 {
1439         ap->a_acquired = B_FALSE;
1440         cv_signal(&ap->a_cv);            /* wake next waiter */
1441 }
1442 
1443 
1444 static void
1445 sbp2_agent_acquire(sbp2_agent_t *ap)
1446 {
1447         mutex_enter(&ap->a_mutex);
1448         sbp2_agent_acquire_locked(ap);
1449         mutex_exit(&ap->a_mutex);
1450 }
1451 
1452 
1453 static void
1454 sbp2_agent_release(sbp2_agent_t *ap)
1455 {
1456         mutex_enter(&ap->a_mutex);
1457         sbp2_agent_release_locked(ap);
1458         mutex_exit(&ap->a_mutex);
1459 }
1460 
1461 
1462 static int
1463 sbp2_agent_keepalive(sbp2_agent_t *ap, int *berr)
1464 {
1465         boolean_t       acquired;
1466         int             ret = SBP2_SUCCESS;
1467 
1468         ASSERT(mutex_owned(&ap->a_mutex));
1469 
1470         if (ap->a_state == SBP2_AGENT_STATE_DEAD) {
1471                 acquired = ap->a_acquired;
1472                 if (!acquired) {
1473                         sbp2_agent_acquire_locked(ap);
1474                 }
1475 
1476                 mutex_exit(&ap->a_mutex);
1477                 ret = sbp2_agent_reset(ap, berr);
1478                 mutex_enter(&ap->a_mutex);
1479 
1480                 if (!acquired) {
1481                         sbp2_agent_release_locked(ap);
1482                 }
1483         }
1484 
1485         return (ret);
1486 }
1487 
1488 #ifndef __lock_lint
1489 static int
1490 sbp2_agent_doorbell(sbp2_agent_t *ap, int *berr)
1491 {
1492         return (SBP2_WQ(ap->a_tgt, ap->a_cmd, ap->a_reg_doorbell, 0, berr));
1493 }
1494 #endif
1495 
1496 /*
1497  * write into ORB_POINTER register and make sure it reached target
1498  *
1499  * From E.2: "If no acknowledgement is received by the initiator after a write
1500  *      to the ORB_POINTER register, the initiator should not retry the write.
1501  *      The recommended method for error recovery is a write to the AGENT_RESET
1502  *      register." So we can retry, but not in case of timeout.
1503  */
1504 static int
1505 sbp2_agent_write_orbp(sbp2_agent_t *ap, uint64_t baddr, int *berr)
1506 {
1507         int             i = 0;
1508         int             ret;
1509 
1510         SBP2_ORBP_SET(ap->a_cmd_data->b_rptr, baddr);
1511         ap->a_cmd_data->b_wptr = ap->a_cmd_data->b_rptr + 8;
1512 
1513         for (;;) {
1514                 ap->a_tgt->t_stat.stat_agent_worbp++;
1515                 if ((ret = SBP2_WB(ap->a_tgt, ap->a_cmd, ap->a_reg_orbp,
1516                     ap->a_cmd_data, 8, berr)) == SBP2_SUCCESS) {
1517                         return (ret);
1518                 }
1519                 ap->a_tgt->t_stat.stat_agent_worbp_fail++;
1520 
1521                 if ((ret == SBP2_ETIMEOUT) ||
1522                     (++i > sbp2_write_orbp_nretries)) {
1523                         break;
1524                 }
1525                 if (sbp2_write_orbp_delay > 0) {
1526                         drv_usecwait(sbp2_write_orbp_delay);
1527                 }
1528         }
1529 
1530         return (ret);
1531 }
1532 
1533 
1534 /*
1535  * reset fetch agent by writing into AGENT_RESET register
1536  */
1537 static int
1538 sbp2_agent_reset(sbp2_agent_t *ap, int *berr)
1539 {
1540         int     i = 0;
1541         int     ret;
1542 
1543         for (;;) {
1544                 ap->a_tgt->t_stat.stat_agent_wreset++;
1545                 if ((ret = SBP2_WQ(ap->a_tgt, ap->a_cmd, ap->a_reg_agent_reset,
1546                     0, berr)) == SBP2_SUCCESS) {
1547                         mutex_enter(&ap->a_mutex);
1548                         ap->a_state = SBP2_AGENT_STATE_RESET;
1549                         mutex_exit(&ap->a_mutex);
1550                         break;
1551                 }
1552 
1553                 ap->a_tgt->t_stat.stat_agent_wreset_fail++;
1554                 if (++i > sbp2_submit_reset_nretries) {
1555                         break;
1556                 }
1557                 if (sbp2_submit_reset_delay > 0) {
1558                         drv_usecwait(sbp2_submit_reset_delay);
1559                 }
1560         }
1561         return (ret);
1562 }
1563 
1564 /*
1565  *
1566  * --- callbacks and timeouts
1567  *
1568  */
1569 /*
1570  * Status FIFO callback for mgt ORB's.
1571  */
1572 /*ARGSUSED*/
1573 static void
1574 sbp2_mgt_status_fifo_wb_cb(sbp2_bus_buf_t *buf, void *reqh, mblk_t **bpp)
1575 {
1576         sbp2_tgt_t      *tp = buf->bb_sbp2_priv;
1577         int             len;
1578         sbp2_status_t   *st;
1579         uint64_t        orbp;
1580 
1581         len = MBLKL(*bpp);
1582 
1583         /* 8 bytes minimum */
1584         if (len < 8) {
1585                 SBP2_BUF_WR_DONE(tp, buf, reqh, SBP2_BUS_BUF_ELENGTH);
1586                 tp->t_stat.stat_status_short++;
1587                 return;
1588         }
1589 
1590         /* convert 2-quadlet header from BE to native endianness */
1591         st = (sbp2_status_t *)(*bpp)->b_rptr;
1592         SBP2_SWAP16_1(st->st_orb_offset_hi);
1593         SBP2_SWAP32_1(st->st_orb_offset_lo);
1594         orbp = ((uint64_t)st->st_orb_offset_hi << 32) | st->st_orb_offset_lo;
1595 
1596         if (orbp != tp->t_mgt_orb_buf.bb_baddr) {
1597                 SBP2_BUF_WR_DONE(tp, buf, reqh, SBP2_BUS_BUF_FAILURE);
1598                 tp->t_stat.stat_status_mgt_notask++;
1599                 return;
1600         }
1601 
1602         /* make a local copy of status block */
1603         bzero(&tp->t_mgt_status, sizeof (sbp2_status_t));
1604         bcopy((*bpp)->b_rptr, &tp->t_mgt_status, len);
1605 
1606         SBP2_BUF_WR_DONE(tp, buf, reqh, SBP2_BUS_BUF_SUCCESS);
1607 
1608         /* wake up waiter */
1609         mutex_enter(&tp->t_mutex);
1610         tp->t_mgt_status_rcvd = B_TRUE;
1611         cv_signal(&tp->t_mgt_status_cv);
1612         mutex_exit(&tp->t_mutex);
1613 }
1614 
1615 static void
1616 sbp2_task_timeout(void *arg)
1617 {
1618         sbp2_task_t     *task = arg;
1619         sbp2_ses_t      *sp = task->ts_ses;
1620         sbp2_agent_t    *ap = &sp->s_agent;
1621 
1622         mutex_enter(&ap->a_mutex);
1623 
1624         /* cancelled? */
1625         if (task->ts_timeout_id == 0) {
1626                 mutex_exit(&ap->a_mutex);
1627                 return;
1628         }
1629         task->ts_timeout_id = 0;
1630         task->ts_time_comp = gethrtime();
1631 
1632         /* avoid race with other callbacks */
1633         if (task->ts_state != SBP2_TASK_PEND) {
1634                 mutex_exit(&ap->a_mutex);
1635                 return;
1636         }
1637 
1638         if (task == ap->a_active_task) {
1639                 ap->a_active_task = NULL;
1640         }
1641         task->ts_error = SBP2_TASK_ERR_TIMEOUT;
1642         task->ts_state = SBP2_TASK_COMP;
1643 
1644         /* we mark agent DEAD so it's reset before next task is submitted */
1645         ap->a_state = SBP2_AGENT_STATE_DEAD;
1646         sp->s_tgt->t_stat.stat_status_dead++;
1647         mutex_exit(&ap->a_mutex);
1648 
1649         sp->s_status_cb(sp->s_status_cb_arg, task);
1650 }
1651 
1652 /*
1653  * Status FIFO callback for command ORB's. Also used for login ORB.
1654  */
1655 /*ARGSUSED*/
1656 static void
1657 sbp2_status_fifo_wb_cb(sbp2_bus_buf_t *buf, void *reqh, mblk_t **bpp)
1658 {
1659         sbp2_ses_t      *sp = buf->bb_sbp2_priv;
1660         sbp2_tgt_t      *tp = sp->s_tgt;
1661         sbp2_agent_t    *ap = &sp->s_agent;
1662         int             len;
1663         sbp2_status_t   *st;
1664         uint8_t         src;
1665         uint64_t        orbp;
1666         sbp2_task_t     *task;
1667         timeout_id_t    timeout_id;
1668 
1669         len = MBLKL(*bpp);
1670 
1671         /* 8 bytes minimum */
1672         if (len < 8) {
1673                 SBP2_BUF_WR_DONE(tp, buf, reqh, SBP2_BUS_BUF_ELENGTH);
1674                 tp->t_stat.stat_status_short++;
1675                 return;
1676         }
1677 
1678         /* convert 2-quadlet header from BE32 to native endianness */
1679         st = (sbp2_status_t *)(*bpp)->b_rptr;
1680         SBP2_SWAP16_1(st->st_orb_offset_hi);
1681         SBP2_SWAP32_1(st->st_orb_offset_lo);
1682 
1683         orbp = ((uint64_t)st->st_orb_offset_hi << 32) | st->st_orb_offset_lo;
1684 
1685         /* login ORB status? */
1686         if (orbp == tp->t_mgt_orb_buf.bb_baddr) {
1687                 bzero(&tp->t_mgt_status, sizeof (sbp2_status_t));
1688                 bcopy((*bpp)->b_rptr, &tp->t_mgt_status, len);
1689 
1690                 SBP2_BUF_WR_DONE(tp, buf, reqh, SBP2_BUS_BUF_SUCCESS);
1691 
1692                 /* wake up waiter */
1693                 mutex_enter(&tp->t_mutex);
1694                 tp->t_mgt_status_rcvd = B_TRUE;
1695                 cv_signal(&tp->t_mgt_status_cv);
1696                 mutex_exit(&tp->t_mutex);
1697                 return;
1698         }
1699 
1700         /* dismiss unsolicited status */
1701         src = st->st_param & SBP2_ST_SRC;
1702         if (src == SBP2_ST_SRC_UNSOLICITED) {
1703                 SBP2_BUF_WR_DONE(tp, buf, reqh, SBP2_BUS_BUF_FAILURE);
1704                 tp->t_stat.stat_status_unsolicited++;
1705                 return;
1706         }
1707 
1708         /* find task corresponding to this ORB pointer */
1709         if ((task = sbp2_ses_orbp2task(sp, orbp)) == NULL) {
1710                 SBP2_BUF_WR_DONE(tp, buf, reqh, SBP2_BUS_BUF_FAILURE);
1711                 tp->t_stat.stat_status_notask++;
1712                 return;
1713         }
1714 
1715         /*
1716          * Copy status block into a local buffer.
1717          *
1718          * Note: (ref: B.2) "SBP-2 permits the return of a status block between
1719          *      two and eight quadlets in length. When a truncated status block
1720          *      is stored, the omited quadlets shall be interpreted as if zero
1721          *      values were stored."
1722          */
1723         bzero(&task->ts_status, sizeof (sbp2_status_t));
1724         bcopy((*bpp)->b_rptr, &task->ts_status, len);
1725 
1726         SBP2_BUF_WR_DONE(tp, buf, reqh, SBP2_BUS_BUF_SUCCESS);
1727 
1728         mutex_enter(&ap->a_mutex);
1729 
1730         if ((timeout_id = task->ts_timeout_id) != 0) {
1731                 task->ts_timeout_id = 0;
1732                 (void) untimeout(timeout_id);
1733         }
1734 
1735         /* determine agent state */
1736         if (st->st_param & SBP2_ST_DEAD) {
1737                 ap->a_state = SBP2_AGENT_STATE_DEAD;
1738                 tp->t_stat.stat_status_dead++;
1739         }
1740 
1741         /* avoid race with other callbacks */
1742         if (task->ts_state != SBP2_TASK_PEND) {
1743                 mutex_exit(&ap->a_mutex);
1744                 return;
1745         }
1746 
1747         if (task == ap->a_active_task) {
1748                 ap->a_active_task = NULL;
1749         }
1750         task->ts_error = SBP2_TASK_ERR_NONE;
1751         task->ts_state = SBP2_TASK_COMP;
1752 
1753         mutex_exit(&ap->a_mutex);
1754 
1755         sp->s_status_cb(sp->s_status_cb_arg, task);       /* notify the driver */
1756 }
1757 
1758 /*
1759  *
1760  * --- other
1761  *
1762  * since mgt agent is shared between LUNs and login sessions,
1763  * it is safer to serialize mgt requests
1764  */
1765 static void
1766 sbp2_mgt_agent_acquire(sbp2_tgt_t *tp)
1767 {
1768         mutex_enter(&tp->t_mutex);
1769         while (tp->t_mgt_agent_acquired) {
1770                 cv_wait(&tp->t_mgt_agent_cv, &tp->t_mutex);
1771         }
1772         tp->t_mgt_agent_acquired = B_TRUE;
1773         mutex_exit(&tp->t_mutex);
1774 }
1775 
1776 static void
1777 sbp2_mgt_agent_release(sbp2_tgt_t *tp)
1778 {
1779         mutex_enter(&tp->t_mutex);
1780         tp->t_mgt_agent_acquired = B_FALSE;
1781         cv_signal(&tp->t_mgt_agent_cv);  /* wake next waiter */
1782         mutex_exit(&tp->t_mutex);
1783 }