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