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