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