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 } 393 if (tp->t_mgt_cmd_data) { 394 freeb(tp->t_mgt_cmd_data); 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 tp->t_mgt_status_rcvd = B_FALSE; 422 423 /* write ORB address into MANAGEMENT_AGENT */ 424 SBP2_ADDR_SET(tp->t_mgt_cmd_data->b_rptr, tp->t_mgt_orb_buf.bb_baddr, 425 0); 426 tp->t_mgt_cmd_data->b_wptr = tp->t_mgt_cmd_data->b_rptr + 8; 427 428 if ((ret = SBP2_WB(tp, tp->t_mgt_cmd, tp->t_mgt_agent, 429 tp->t_mgt_cmd_data, 8, berr)) != SBP2_SUCCESS) { 430 return (ret); 431 } 432 433 /* wait for login response */ 434 mutex_enter(&tp->t_mutex); 435 until = ddi_get_lbolt() + drv_usectohz(tp->t_mot * 1000); 436 ret = 1; 437 438 while (!tp->t_mgt_status_rcvd && (ret > 0)) { 439 ret = cv_timedwait(&tp->t_mgt_status_cv, &tp->t_mutex, until); 440 } 441 442 if (!tp->t_mgt_status_rcvd) { 443 ret = SBP2_ETIMEOUT; 444 } else if ((tp->t_mgt_status.st_param & SBP2_ST_RESP) == 445 SBP2_ST_RESP_COMPLETE) { 446 ret = SBP2_SUCCESS; 447 } else { 448 ret = SBP2_FAILURE; 449 } 450 mutex_exit(&tp->t_mutex); 451 452 return (ret); 453 } 454 455 /* 456 * Send task management request, one of: 457 * 458 * ABORT TASK, ABORT TASK SET, LOGICAL UNIT RESET, TARGET RESET 459 */ 460 static int 461 sbp2_tgt_task_mgt_request(sbp2_tgt_t *tp, uint16_t id, int func, uint64_t orbp, 462 int *berr) 463 { 464 sbp2_task_mgt_orb_t *torb; 465 int ret; 466 467 sbp2_mgt_agent_acquire(tp); 468 469 torb = (sbp2_task_mgt_orb_t *)tp->t_mgt_orb_buf.bb_kaddr; 470 bzero(torb, sizeof (sbp2_task_mgt_orb_t)); 471 SBP2_ORBP_SET(torb->to_orb, orbp); 472 torb->to_params = SBP2_SWAP16(func | SBP2_ORB_NOTIFY | 473 SBP2_ORB_RQ_FMT_SBP2); 474 torb->to_login_id = SBP2_SWAP16(id); 475 SBP2_ADDR_SET(torb->to_status_fifo, tp->t_mgt_status_fifo_buf.bb_baddr, 476 0); 477 478 ret = sbp2_tgt_mgt_request(tp, berr); 479 480 sbp2_mgt_agent_release(tp); 481 482 return (ret); 483 } 484 485 int 486 sbp2_tgt_reset(sbp2_tgt_t *tp, int *berr) 487 { 488 sbp2_lun_t *lp = &tp->t_lun[0]; 489 int ret; 490 491 /* issue TARGET RESET */ 492 if ((ret = sbp2_tgt_task_mgt_request(tp, lp->l_login_resp.lr_login_id, 493 SBP2_ORB_MGT_FUNC_TARGET_RESET, 0, berr)) != SBP2_SUCCESS) { 494 return (ret); 495 } 496 497 return (SBP2_SUCCESS); 498 } 499 500 int 501 sbp2_tgt_get_cfgrom(sbp2_tgt_t *tp, sbp2_cfgrom_t **crpp) 502 { 503 *crpp = &tp->t_cfgrom; 504 return (SBP2_SUCCESS); 505 } 506 507 int 508 sbp2_tgt_get_lun_cnt(sbp2_tgt_t *tp) 509 { 510 return (tp->t_nluns); 511 } 512 513 sbp2_lun_t * 514 sbp2_tgt_get_lun(sbp2_tgt_t *tp, int num) 515 { 516 if (num < tp->t_nluns) { 517 return (&tp->t_lun[num]); 518 } else { 519 return (NULL); 520 } 521 } 522 523 /* 524 * 525 * --- lun routines 526 * 527 */ 528 int 529 sbp2_lun_reset(sbp2_lun_t *lp, int *berr) 530 { 531 sbp2_tgt_t *tp = lp->l_tgt; 532 sbp2_ses_t *sp = lp->l_ses; 533 sbp2_task_t *task = NULL; 534 int ret; 535 536 /* issue LOGICAL UNIT RESET */ 537 if ((ret = sbp2_tgt_task_mgt_request(tp, lp->l_login_resp.lr_login_id, 538 SBP2_ORB_MGT_FUNC_LUN_RESET, 0, berr)) != SBP2_SUCCESS) { 539 return (ret); 540 } 541 542 /* mark all pending tasks reset and notify the driver */ 543 mutex_enter(&sp->s_task_mutex); 544 for (task = sp->s_task_head; task != NULL; task = task->ts_next) { 545 if (task->ts_state < SBP2_TASK_COMP) { 546 task->ts_error = SBP2_TASK_ERR_LUN_RESET; 547 task->ts_state = SBP2_TASK_COMP; 548 } 549 } 550 mutex_exit(&sp->s_task_mutex); 551 552 sp->s_status_cb(sp->s_status_cb_arg, NULL); 553 554 return (SBP2_SUCCESS); 555 } 556 557 int 558 sbp2_lun_login(sbp2_lun_t *lp, sbp2_ses_t **spp, 559 void (*cb)(void *, sbp2_task_t *), void *cb_arg, int *berr) 560 { 561 sbp2_tgt_t *tp = lp->l_tgt; 562 sbp2_ses_t *sp; 563 sbp2_login_orb_t *lorb; 564 int ret; 565 566 if (cb == NULL) { 567 return (SBP2_EINVAL); 568 } 569 570 /* multiple sessions not supported yet */ 571 if (lp->l_ses != NULL) { 572 return (SBP2_EALREADY); 573 } 574 575 if ((ret = sbp2_ses_init(&sp, lp, cb, cb_arg)) != SBP2_SUCCESS) { 576 return (ret); 577 } 578 lp->l_ses = sp; 579 580 sbp2_mgt_agent_acquire(tp); 581 582 /* prepare login ORB */ 583 mutex_enter(&tp->t_mutex); 584 lorb = (sbp2_login_orb_t *)tp->t_mgt_orb_buf.bb_kaddr; 585 bzero(lorb, sizeof (sbp2_login_orb_t)); 586 SBP2_ADDR_SET(lorb->lo_resp, tp->t_mgt_login_resp_buf.bb_baddr, 0); 587 lorb->lo_params = SBP2_SWAP16(SBP2_ORB_MGT_FUNC_LOGIN | 588 SBP2_ORB_LOGIN_EXCL | SBP2_ORB_NOTIFY | SBP2_ORB_RQ_FMT_SBP2); 589 lorb->lo_lun = SBP2_SWAP16(lp->l_lun); 590 lorb->lo_resp_len = SBP2_SWAP16(tp->t_mgt_login_resp_buf.bb_len); 591 SBP2_ADDR_SET(lorb->lo_status_fifo, sp->s_status_fifo_buf.bb_baddr, 0); 592 593 bzero(tp->t_mgt_login_resp_buf.bb_kaddr, sizeof (sbp2_login_resp_t)); 594 595 lp->l_logged_in = B_FALSE; 596 mutex_exit(&tp->t_mutex); 597 598 /* send request */ 599 if ((ret = sbp2_tgt_mgt_request(tp, berr)) != SBP2_SUCCESS) { 600 sbp2_mgt_agent_release(tp); 601 sbp2_ses_fini(lp->l_ses); 602 lp->l_ses = NULL; 603 return (ret); 604 } 605 606 /* retrieve response data (XXX sanity checks?) */ 607 mutex_enter(&tp->t_mutex); 608 (void) SBP2_SYNC_BUF(tp, &tp->t_mgt_login_resp_buf, 0, 0, 609 DDI_DMA_SYNC_FORKERNEL); 610 bcopy(tp->t_mgt_login_resp_buf.bb_kaddr, &lp->l_login_resp, 611 sizeof (sbp2_login_resp_t)); 612 613 /* convert from BE to native endianness */ 614 SBP2_SWAP16_1(lp->l_login_resp.lr_len); 615 SBP2_SWAP16_1(lp->l_login_resp.lr_login_id); 616 SBP2_SWAP32_2(lp->l_login_resp.lr_cmd_agent); 617 SBP2_SWAP16_1(lp->l_login_resp.lr_reconnect_hold); 618 lp->l_login_resp.lr_reconnect_hold++; 619 620 sp->s_agent_offset = SBP2_ADDR2UINT64(lp->l_login_resp.lr_cmd_agent); 621 622 lp->l_logged_in = B_TRUE; 623 mutex_exit(&tp->t_mutex); 624 625 sbp2_mgt_agent_release(tp); 626 627 if ((ret = sbp2_agent_init(&sp->s_agent, sp->s_agent_offset, tp)) != 628 SBP2_SUCCESS) { 629 sbp2_ses_fini(sp); 630 lp->l_ses = NULL; 631 return (ret); 632 } 633 634 *spp = lp->l_ses; 635 return (SBP2_SUCCESS); 636 } 637 638 /*ARGSUSED*/ 639 int 640 sbp2_lun_logout(sbp2_lun_t *lp, sbp2_ses_t **sp, int *berr, boolean_t phys) 641 { 642 sbp2_tgt_t *tp = lp->l_tgt; 643 644 ASSERT(*sp == lp->l_ses); 645 646 mutex_enter(&tp->t_mutex); 647 if (lp->l_logged_in) { 648 lp->l_logged_in = B_FALSE; 649 /* do physical LOGOUT if requested */ 650 if (phys) { 651 mutex_exit(&tp->t_mutex); 652 sbp2_lun_logout_orb(lp, tp, berr); 653 mutex_enter(&tp->t_mutex); 654 } 655 } 656 657 sbp2_agent_fini(&lp->l_ses->s_agent); 658 sbp2_ses_fini(lp->l_ses); 659 lp->l_ses = NULL; 660 *sp = NULL; 661 mutex_exit(&tp->t_mutex); 662 663 return (SBP2_SUCCESS); 664 } 665 666 /* 667 * Issue LOGOUT mgt orb and wait for response. We are not interested in 668 * the success at the time, since the device may be disconnected or hung, 669 * just trying to make the best effort. 670 */ 671 static void 672 sbp2_lun_logout_orb(sbp2_lun_t *lp, sbp2_tgt_t *tp, int *berr) 673 { 674 sbp2_logout_orb_t *lorb; 675 676 sbp2_mgt_agent_acquire(tp); 677 678 /* prepare logout ORB */ 679 lorb = (sbp2_logout_orb_t *)tp->t_mgt_orb_buf.bb_kaddr; 680 bzero(lorb, sizeof (sbp2_logout_orb_t)); 681 lorb->lo_params = SBP2_SWAP16(SBP2_ORB_MGT_FUNC_LOGOUT | 682 SBP2_ORB_NOTIFY | SBP2_ORB_RQ_FMT_SBP2); 683 lorb->lo_login_id = SBP2_SWAP16(lp->l_login_resp.lr_login_id); 684 SBP2_ADDR_SET(lorb->lo_status_fifo, tp->t_mgt_status_fifo_buf.bb_baddr, 685 0); 686 687 /* send request */ 688 (void) sbp2_tgt_mgt_request(tp, berr); 689 690 sbp2_mgt_agent_release(tp); 691 } 692 693 static boolean_t 694 sbp2_lun_accepting_tasks(sbp2_lun_t *lp) 695 { 696 sbp2_tgt_t *tp = lp->l_tgt; 697 boolean_t ret; 698 699 mutex_enter(&tp->t_mutex); 700 ret = ((lp->l_ses != NULL) && lp->l_logged_in && !lp->l_reconnecting); 701 mutex_exit(&tp->t_mutex); 702 return (ret); 703 } 704 705 /* 706 * 707 * --- session routines 708 * 709 */ 710 static int 711 sbp2_ses_init(sbp2_ses_t **spp, sbp2_lun_t *lp, 712 void (*cb)(void *, sbp2_task_t *), void *cb_arg) 713 { 714 sbp2_tgt_t *tp = lp->l_tgt; 715 sbp2_ses_t *sp; 716 int ret; 717 718 sp = kmem_zalloc(sizeof (sbp2_ses_t), KM_SLEEP); 719 720 sp->s_tgt = tp; 721 sp->s_lun = lp; 722 sp->s_status_cb = cb; 723 sp->s_status_cb_arg = cb_arg; 724 725 mutex_init(&sp->s_mutex, NULL, MUTEX_DRIVER, 726 SBP2_GET_IBLOCK_COOKIE(tp)); 727 mutex_init(&sp->s_task_mutex, NULL, MUTEX_DRIVER, 728 SBP2_GET_IBLOCK_COOKIE(tp)); 729 730 /* 731 * status FIFO for block requests 732 */ 733 sp->s_status_fifo_buf.bb_len = sizeof (sbp2_status_t); 734 sp->s_status_fifo_buf.bb_flags = SBP2_BUS_BUF_WR_POSTED; 735 sp->s_status_fifo_buf.bb_wb_cb = sbp2_status_fifo_wb_cb; 736 sp->s_status_fifo_buf.bb_sbp2_priv = sp; 737 if ((ret = SBP2_ALLOC_BUF(tp, &sp->s_status_fifo_buf)) != 738 SBP2_SUCCESS) { 739 sbp2_ses_fini(sp); 740 return (ret); 741 } 742 743 *spp = sp; 744 return (SBP2_SUCCESS); 745 } 746 747 748 static void 749 sbp2_ses_fini(sbp2_ses_t *sp) 750 { 751 sbp2_tgt_t *tp = sp->s_lun->l_tgt; 752 753 if (sp->s_status_fifo_buf.bb_hdl != NULL) { 754 SBP2_FREE_BUF(tp, &sp->s_status_fifo_buf); 755 } 756 757 mutex_destroy(&sp->s_task_mutex); 758 mutex_destroy(&sp->s_mutex); 759 760 kmem_free(sp, sizeof (sbp2_ses_t)); 761 } 762 763 int 764 sbp2_ses_reconnect(sbp2_ses_t *sp, int *berr, uint16_t nodeID) 765 { 766 sbp2_tgt_t *tp = sp->s_tgt; 767 sbp2_lun_t *lp = sp->s_lun; 768 int ret; 769 770 /* prevent new tasks from being submitted */ 771 mutex_enter(&tp->t_mutex); 772 lp->l_reconnecting = B_TRUE; 773 mutex_exit(&tp->t_mutex); 774 775 /* 776 * From 10.5 Task management event matrix: 777 * Immediately upon detection of a bus reset, all command 778 * block fetch agents transition to the reset state and 779 * their associated task sets are cleared without 780 * the return of completion status. 781 * 782 * Reset pending tasks so we can retry them later. 783 */ 784 sbp2_ses_reset_pending_tasks(sp, nodeID); 785 786 ret = sbp2_ses_reconnect_orb(sp, berr); 787 788 mutex_enter(&tp->t_mutex); 789 lp->l_reconnecting = B_FALSE; 790 mutex_exit(&tp->t_mutex); 791 792 return (ret); 793 } 794 795 /* 796 * Send reconnect ORB. If operation fails, set lp->l_logged_in = B_FALSE. 797 */ 798 static int 799 sbp2_ses_reconnect_orb(sbp2_ses_t *sp, int *berr) 800 { 801 sbp2_tgt_t *tp = sp->s_tgt; 802 sbp2_lun_t *lp = sp->s_lun; 803 sbp2_agent_t *ap = &sp->s_agent; 804 sbp2_reconnect_orb_t *rorb; 805 int ret; 806 807 sbp2_mgt_agent_acquire(tp); 808 809 /* prepare login ORB */ 810 rorb = (sbp2_reconnect_orb_t *)tp->t_mgt_orb_buf.bb_kaddr; 811 bzero(rorb, sizeof (sbp2_reconnect_orb_t)); 812 rorb->ro_params = SBP2_SWAP16(SBP2_ORB_MGT_FUNC_RECONNECT | 813 SBP2_ORB_NOTIFY | SBP2_ORB_RQ_FMT_SBP2); 814 rorb->ro_login_id = SBP2_SWAP16(lp->l_login_resp.lr_login_id); 815 SBP2_ADDR_SET(rorb->ro_status_fifo, tp->t_mgt_status_fifo_buf.bb_baddr, 816 0); 817 818 /* send request */ 819 if ((ret = sbp2_tgt_mgt_request(tp, berr)) != SBP2_SUCCESS) { 820 mutex_enter(&tp->t_mutex); 821 lp->l_logged_in = B_FALSE; 822 mutex_exit(&tp->t_mutex); 823 } else { 824 /* after successful reset fetch agent is in RESET state */ 825 mutex_enter(&ap->a_mutex); 826 ap->a_state = SBP2_AGENT_STATE_RESET; 827 mutex_exit(&ap->a_mutex); 828 } 829 830 sbp2_mgt_agent_release(tp); 831 832 return (ret); 833 } 834 835 836 static sbp2_task_t * 837 sbp2_ses_orbp2task(sbp2_ses_t *sp, uint64_t orbp) 838 { 839 sbp2_task_t *task; 840 841 mutex_enter(&sp->s_task_mutex); 842 for (task = sp->s_task_head; task != NULL; task = task->ts_next) { 843 if (task->ts_buf->bb_baddr == orbp) { 844 break; 845 } 846 } 847 mutex_exit(&sp->s_task_mutex); 848 return (task); 849 } 850 851 /* 852 * This is where tasks (command ORB's) are signalled to the target. 853 * 'task' argument is allowed to be NULL, in which case the task will be 854 * taken from the current task list. 855 * 856 * Tasks are signalled one at a time by writing into ORB_POINTER register. 857 * While SBP-2 allows dynamic task list updates and using DOORBELL register, 858 * some devices have bugs that prevent using this strategy: e.g. some LaCie 859 * HDD's can corrupt data. Data integrity is more important than performance. 860 */ 861 int 862 sbp2_ses_submit_task(sbp2_ses_t *sp, sbp2_task_t *new_task) 863 { 864 sbp2_agent_t *ap = &sp->s_agent; 865 sbp2_tgt_t *tp = sp->s_tgt; 866 sbp2_task_t *task; /* task actually being submitted */ 867 boolean_t callback; 868 timeout_id_t timeout_id; 869 int ret; 870 871 if (!sbp2_lun_accepting_tasks(sp->s_lun)) { 872 return (SBP2_ENODEV); 873 } 874 875 sbp2_agent_acquire(ap); /* serialize */ 876 877 mutex_enter(&ap->a_mutex); 878 879 /* if task provided, append it to the list */ 880 if (new_task != NULL) { 881 ASSERT(new_task->ts_state == SBP2_TASK_INIT); 882 sbp2_ses_append_task(sp, new_task); 883 } 884 885 /* if there is already a task in flight, exit */ 886 if ((ap->a_active_task != NULL) && 887 (ap->a_active_task->ts_state == SBP2_TASK_PEND)) { 888 mutex_exit(&ap->a_mutex); 889 sbp2_agent_release(ap); 890 return (SBP2_SUCCESS); 891 } 892 893 /* no active task, grab the first one on the list in INIT state */ 894 ap->a_active_task = sbp2_ses_find_task_state(sp, SBP2_TASK_INIT); 895 if (ap->a_active_task == NULL) { 896 mutex_exit(&ap->a_mutex); 897 sbp2_agent_release(ap); 898 return (SBP2_SUCCESS); 899 } 900 task = ap->a_active_task; 901 task->ts_ses = sp; 902 task->ts_state = SBP2_TASK_PEND; 903 904 /* can't work with a dead agent */ 905 if (sbp2_agent_keepalive(ap, &task->ts_bus_error) != SBP2_SUCCESS) { 906 task->ts_error = SBP2_TASK_ERR_DEAD; 907 goto error; 908 } 909 910 /* 911 * In theory, we should schedule task timeout after it's been submitted. 912 * However, some fast tasks complete even before timeout is scheduled. 913 * To avoid additional complications in the code, schedule timeout now. 914 */ 915 ASSERT(task->ts_timeout_id == 0); 916 task->ts_time_start = gethrtime(); 917 if (task->ts_timeout > 0) { 918 task->ts_timeout_id = timeout(sbp2_task_timeout, task, 919 task->ts_timeout * drv_usectohz(1000000)); 920 } 921 922 /* notify fetch agent */ 923 ap->a_state = SBP2_AGENT_STATE_ACTIVE; 924 mutex_exit(&ap->a_mutex); 925 ret = sbp2_agent_write_orbp(ap, task->ts_buf->bb_baddr, 926 &task->ts_bus_error); 927 tp->t_stat.stat_submit_orbp++; 928 mutex_enter(&ap->a_mutex); 929 930 if (ret != SBP2_SUCCESS) { 931 ap->a_state = SBP2_AGENT_STATE_DEAD; 932 tp->t_stat.stat_status_dead++; 933 934 if (task->ts_timeout_id != 0) { 935 timeout_id = task->ts_timeout_id; 936 task->ts_timeout_id = 0; 937 (void) untimeout(timeout_id); 938 } 939 task->ts_error = SBP2_TASK_ERR_BUS; 940 goto error; 941 } 942 943 mutex_exit(&ap->a_mutex); 944 945 sbp2_agent_release(ap); 946 return (SBP2_SUCCESS); 947 948 error: 949 /* 950 * Return immediate error if failed task is the one being submitted, 951 * otherwise use callback. 952 */ 953 callback = (ap->a_active_task != new_task); 954 task = ap->a_active_task; 955 ap->a_active_task = NULL; 956 mutex_exit(&ap->a_mutex); 957 sbp2_agent_release(ap); 958 959 /* 960 * Remove task from the list. It is important not to change task state 961 * to SBP2_TASK_COMP while it's still on the list, to avoid race with 962 * upper layer driver (e.g. scsa1394). 963 */ 964 ret = sbp2_ses_remove_task(sp, new_task); 965 ASSERT(ret == SBP2_SUCCESS); 966 new_task->ts_state = SBP2_TASK_COMP; 967 968 if (callback) { 969 sp->s_status_cb(sp->s_status_cb_arg, new_task); 970 return (SBP2_SUCCESS); 971 } else { 972 /* upper layer driver is responsible to call nudge */ 973 return (SBP2_FAILURE); 974 } 975 } 976 977 void 978 sbp2_ses_nudge(sbp2_ses_t *sp) 979 { 980 (void) sbp2_ses_submit_task(sp, NULL); 981 } 982 983 /* 984 * append task to the task list 985 */ 986 static void 987 sbp2_ses_append_task(sbp2_ses_t *sp, sbp2_task_t *task) 988 { 989 sbp2_tgt_t *tp = sp->s_tgt; 990 991 mutex_enter(&sp->s_task_mutex); 992 if (sp->s_task_head == NULL) { 993 ASSERT(sp->s_task_tail == NULL); 994 ASSERT(sp->s_task_cnt == 0); 995 task->ts_prev = task->ts_next = NULL; 996 sp->s_task_head = sp->s_task_tail = task; 997 } else { 998 ASSERT(sp->s_task_cnt > 0); 999 task->ts_next = NULL; 1000 task->ts_prev = sp->s_task_tail; 1001 sp->s_task_tail->ts_next = task; 1002 sp->s_task_tail = task; 1003 } 1004 ASSERT(task != task->ts_prev); 1005 ASSERT(task != task->ts_next); 1006 1007 sp->s_task_cnt++; 1008 if (sp->s_task_cnt > tp->t_stat.stat_task_max) { 1009 tp->t_stat.stat_task_max = sp->s_task_cnt; 1010 } 1011 mutex_exit(&sp->s_task_mutex); 1012 } 1013 1014 /* 1015 * remove task from the task list 1016 */ 1017 static int 1018 sbp2_ses_remove_task_locked(sbp2_ses_t *sp, sbp2_task_t *task) 1019 { 1020 sp->s_task_cnt--; 1021 if (task == sp->s_task_head) { /* first */ 1022 ASSERT(task->ts_prev == NULL); 1023 if (task->ts_next == NULL) { /* and last */ 1024 ASSERT(sp->s_task_cnt == 0); 1025 sp->s_task_head = sp->s_task_tail = NULL; 1026 } else { /* but not last */ 1027 sp->s_task_head = task->ts_next; 1028 sp->s_task_head->ts_prev = NULL; 1029 } 1030 } else if (task == sp->s_task_tail) { /* last but not first */ 1031 ASSERT(task->ts_next == NULL); 1032 sp->s_task_tail = task->ts_prev; 1033 sp->s_task_tail->ts_next = NULL; 1034 } else { /* in the middle */ 1035 task->ts_prev->ts_next = task->ts_next; 1036 task->ts_next->ts_prev = task->ts_prev; 1037 } 1038 task->ts_prev = task->ts_next = NULL; 1039 ASSERT(sp->s_task_cnt >= 0); 1040 1041 return (SBP2_SUCCESS); 1042 } 1043 1044 int 1045 sbp2_ses_remove_task(sbp2_ses_t *sp, sbp2_task_t *task) 1046 { 1047 int ret; 1048 1049 mutex_enter(&sp->s_task_mutex); 1050 ret = sbp2_ses_remove_task_locked(sp, task); 1051 mutex_exit(&sp->s_task_mutex); 1052 1053 return (ret); 1054 } 1055 1056 /* 1057 * Return first task on the list in specified state. 1058 */ 1059 sbp2_task_t * 1060 sbp2_ses_find_task_state(sbp2_ses_t *sp, sbp2_task_state_t state) 1061 { 1062 sbp2_task_t *task = NULL; 1063 1064 mutex_enter(&sp->s_task_mutex); 1065 for (task = sp->s_task_head; task != NULL; task = task->ts_next) { 1066 if (task->ts_state == state) { 1067 break; 1068 } 1069 } 1070 mutex_exit(&sp->s_task_mutex); 1071 1072 return (task); 1073 } 1074 1075 /* 1076 * Remove first task on the list. Returns pointer to the removed task or NULL. 1077 */ 1078 sbp2_task_t * 1079 sbp2_ses_remove_first_task(sbp2_ses_t *sp) 1080 { 1081 sbp2_task_t *task = NULL; 1082 1083 mutex_enter(&sp->s_task_mutex); 1084 task = sp->s_task_head; 1085 if (task != NULL) { 1086 (void) sbp2_ses_remove_task_locked(sp, task); 1087 } 1088 mutex_exit(&sp->s_task_mutex); 1089 1090 return (task); 1091 } 1092 1093 /* 1094 * Remove first task on the list only if it's in specified state. 1095 * Returns pointer to the removed task or NULL. 1096 */ 1097 sbp2_task_t * 1098 sbp2_ses_remove_first_task_state(sbp2_ses_t *sp, sbp2_task_state_t state) 1099 { 1100 sbp2_task_t *task = NULL; 1101 1102 mutex_enter(&sp->s_task_mutex); 1103 if ((sp->s_task_head != NULL) && (sp->s_task_head->ts_state == state)) { 1104 task = sp->s_task_head; 1105 (void) sbp2_ses_remove_task_locked(sp, task); 1106 } 1107 mutex_exit(&sp->s_task_mutex); 1108 1109 return (task); 1110 } 1111 1112 /* 1113 * Remove first task on the list. If there's timeout, untimeout it. 1114 * Returns pointer to the removed task or NULL. 1115 */ 1116 sbp2_task_t * 1117 sbp2_ses_cancel_first_task(sbp2_ses_t *sp) 1118 { 1119 sbp2_task_t *task = NULL; 1120 timeout_id_t timeout_id; 1121 1122 mutex_enter(&sp->s_task_mutex); 1123 task = sp->s_task_head; 1124 if (task != NULL) { 1125 (void) sbp2_ses_remove_task_locked(sp, task); 1126 } 1127 mutex_exit(&sp->s_task_mutex); 1128 1129 if ((task != NULL) && ((timeout_id = task->ts_timeout_id) != 0)) { 1130 task->ts_timeout_id = 0; 1131 (void) untimeout(timeout_id); 1132 } 1133 1134 return (task); 1135 } 1136 1137 /* 1138 * Reset pending tasks on the list to their initial state. 1139 */ 1140 static void 1141 sbp2_ses_reset_pending_tasks(sbp2_ses_t *sp, uint16_t nodeID) 1142 { 1143 sbp2_agent_t *ap = &sp->s_agent; 1144 sbp2_task_t *task = NULL; 1145 timeout_id_t timeout_id; 1146 sbp2_cmd_orb_t *orb; 1147 1148 mutex_enter(&sp->s_task_mutex); 1149 for (task = sp->s_task_head; task != NULL; task = task->ts_next) { 1150 task->ts_state = SBP2_TASK_INIT; 1151 1152 /* cancel timeout */ 1153 if ((timeout_id = task->ts_timeout_id) != 0) { 1154 task->ts_timeout_id = 0; 1155 (void) untimeout(timeout_id); 1156 } 1157 1158 /* update ORB nodeID */ 1159 orb = (sbp2_cmd_orb_t *)sbp2_task_orb_kaddr(task); 1160 *(uint16_t *)orb->co_data_descr = SBP2_SWAP16(nodeID); 1161 sbp2_task_orb_sync(sp->s_lun, task, DDI_DMA_SYNC_FORDEV); 1162 } 1163 mutex_exit(&sp->s_task_mutex); 1164 1165 mutex_enter(&ap->a_mutex); 1166 ap->a_active_task = NULL; 1167 mutex_exit(&ap->a_mutex); 1168 } 1169 1170 int 1171 sbp2_ses_agent_reset(sbp2_ses_t *sp, int *berr) 1172 { 1173 return (sbp2_agent_reset(&sp->s_agent, berr)); 1174 } 1175 1176 int 1177 sbp2_ses_abort_task(sbp2_ses_t *sp, sbp2_task_t *task, int *berr) 1178 { 1179 sbp2_tgt_t *tp = sp->s_tgt; 1180 sbp2_lun_t *lp = sp->s_lun; 1181 uint16_t params; 1182 sbp2_cmd_orb_t *orb = (sbp2_cmd_orb_t *)task->ts_buf->bb_kaddr; 1183 int ret = SBP2_SUCCESS; 1184 1185 /* mark ORB as dummy ORB */ 1186 params = (orb->co_params & ~SBP2_ORB_RQ_FMT) | SBP2_ORB_RQ_FMT_DUMMY; 1187 orb->co_params = params; 1188 (void) SBP2_SYNC_BUF(tp, task->ts_buf, 0, 0, DDI_DMA_SYNC_FORDEV); 1189 1190 ret = sbp2_tgt_task_mgt_request(tp, lp->l_login_resp.lr_login_id, 1191 SBP2_ORB_MGT_FUNC_ABORT_TASK, task->ts_buf->bb_baddr, berr); 1192 1193 return (ret); 1194 } 1195 1196 1197 int 1198 sbp2_ses_abort_task_set(sbp2_ses_t *sp, int *berr) 1199 { 1200 sbp2_tgt_t *tp = sp->s_tgt; 1201 sbp2_lun_t *lp = sp->s_lun; 1202 int ret; 1203 1204 ret = sbp2_tgt_task_mgt_request(tp, lp->l_login_resp.lr_login_id, 1205 SBP2_ORB_MGT_FUNC_ABORT_TASK_SET, 0, berr); 1206 1207 return (ret); 1208 } 1209 1210 1211 /* 1212 * 1213 * ORB functions 1214 * 1215 * allocate ORB resources 1216 * 1217 * we maintain a freelist of ORB's for faster allocation 1218 */ 1219 /*ARGSUSED*/ 1220 static sbp2_bus_buf_t * 1221 sbp2_orb_freelist_get(sbp2_lun_t *lp, sbp2_task_t *task, int len) 1222 { 1223 sbp2_buf_list_t *bl = &lp->l_orb_freelist; 1224 sbp2_bus_buf_t *buf = NULL; 1225 1226 mutex_enter(&bl->bl_mutex); 1227 if ((bl->bl_head != NULL) && (bl->bl_head->bb_len == len)) { 1228 buf = bl->bl_head; 1229 bl->bl_head = buf->bb_next; 1230 if (bl->bl_tail == buf) { /* last one? */ 1231 ASSERT(bl->bl_head == NULL); 1232 bl->bl_tail = NULL; 1233 } 1234 bl->bl_len--; 1235 buf->bb_next = NULL; 1236 } 1237 mutex_exit(&bl->bl_mutex); 1238 1239 return (buf); 1240 } 1241 1242 static int 1243 sbp2_orb_freelist_put(sbp2_lun_t *lp, sbp2_bus_buf_t *buf) 1244 { 1245 sbp2_buf_list_t *bl = &lp->l_orb_freelist; 1246 int ret; 1247 1248 mutex_enter(&bl->bl_mutex); 1249 if (bl->bl_len < SBP2_ORB_FREELIST_MAX) { 1250 if (bl->bl_head == NULL) { 1251 ASSERT(bl->bl_tail == NULL); 1252 bl->bl_head = bl->bl_tail = buf; 1253 } else { 1254 bl->bl_tail->bb_next = buf; 1255 bl->bl_tail = buf; 1256 } 1257 buf->bb_next = NULL; 1258 bl->bl_len++; 1259 ret = SBP2_SUCCESS; 1260 } else { 1261 ret = SBP2_FAILURE; 1262 } 1263 mutex_exit(&bl->bl_mutex); 1264 1265 return (ret); 1266 } 1267 1268 static void 1269 sbp2_orb_freelist_destroy(sbp2_lun_t *lp) 1270 { 1271 sbp2_tgt_t *tp = lp->l_tgt; 1272 sbp2_buf_list_t *bl = &lp->l_orb_freelist; 1273 sbp2_bus_buf_t *buf, *buf_next; 1274 1275 mutex_enter(&bl->bl_mutex); 1276 for (buf = bl->bl_head; buf != NULL; ) { 1277 SBP2_FREE_BUF(tp, buf); 1278 buf_next = buf->bb_next; 1279 kmem_free(buf, sizeof (sbp2_bus_buf_t)); 1280 buf = buf_next; 1281 } 1282 bl->bl_head = bl->bl_tail = NULL; 1283 mutex_exit(&bl->bl_mutex); 1284 } 1285 1286 int 1287 sbp2_task_orb_alloc(sbp2_lun_t *lp, sbp2_task_t *task, int len) 1288 { 1289 sbp2_tgt_t *tp = lp->l_tgt; 1290 int buf_len; 1291 int ret; 1292 1293 buf_len = SBP2_ORB_SIZE_ROUNDUP(tp, len); 1294 1295 /* try freelist first */ 1296 if ((task->ts_buf = sbp2_orb_freelist_get(lp, task, buf_len)) != NULL) { 1297 return (SBP2_SUCCESS); 1298 } 1299 1300 /* if no free buffers, allocate new */ 1301 task->ts_buf = kmem_zalloc(sizeof (sbp2_bus_buf_t), KM_SLEEP); 1302 task->ts_buf->bb_len = buf_len; 1303 task->ts_buf->bb_flags = SBP2_BUS_BUF_DMA | SBP2_BUS_BUF_RD; 1304 if ((ret = SBP2_ALLOC_BUF(tp, task->ts_buf)) != SBP2_SUCCESS) { 1305 kmem_free(task->ts_buf, sizeof (sbp2_bus_buf_t)); 1306 task->ts_buf = NULL; 1307 } 1308 1309 return (ret); 1310 } 1311 1312 void 1313 sbp2_task_orb_free(sbp2_lun_t *lp, sbp2_task_t *task) 1314 { 1315 sbp2_tgt_t *tp = lp->l_tgt; 1316 1317 if (task->ts_buf != NULL) { 1318 if (sbp2_orb_freelist_put(lp, task->ts_buf) != SBP2_SUCCESS) { 1319 SBP2_FREE_BUF(tp, task->ts_buf); 1320 kmem_free(task->ts_buf, sizeof (sbp2_bus_buf_t)); 1321 } 1322 task->ts_buf = NULL; 1323 } 1324 } 1325 1326 void * 1327 sbp2_task_orb_kaddr(sbp2_task_t *task) 1328 { 1329 return (task->ts_buf->bb_kaddr); 1330 } 1331 1332 void 1333 sbp2_task_orb_sync(sbp2_lun_t *lp, sbp2_task_t *task, int flags) 1334 { 1335 (void) SBP2_SYNC_BUF(lp->l_tgt, task->ts_buf, 0, 0, flags); 1336 } 1337 1338 /* 1339 * 1340 * --- fetch agent routines 1341 * 1342 */ 1343 static int 1344 sbp2_agent_init(sbp2_agent_t *ap, uint64_t offset, sbp2_tgt_t *tp) 1345 { 1346 int ret; 1347 1348 /* paranoia */ 1349 if (offset == 0) { 1350 return (SBP2_FAILURE); 1351 } 1352 1353 ap->a_tgt = tp; 1354 1355 ap->a_reg_agent_state = offset + SBP2_AGENT_STATE_OFFSET; 1356 ap->a_reg_agent_reset = offset + SBP2_AGENT_RESET_OFFSET; 1357 ap->a_reg_orbp = offset + SBP2_ORB_POINTER_OFFSET; 1358 ap->a_reg_doorbell = offset + SBP2_DOORBELL_OFFSET; 1359 ap->a_reg_unsol_status_enable = offset + 1360 SBP2_UNSOLICITED_STATUS_ENABLE_OFFSET; 1361 1362 /* 1363 * allocate bus commands 1364 */ 1365 if ((ret = SBP2_ALLOC_CMD(tp, &ap->a_cmd, 0)) != SBP2_SUCCESS) { 1366 return (ret); 1367 } 1368 ap->a_cmd_data = allocb(sizeof (sbp2_orbp_t), BPRI_HI); 1369 if (ap->a_cmd_data == NULL) { 1370 sbp2_agent_fini(ap); 1371 return (SBP2_ENOMEM); 1372 } 1373 1374 mutex_init(&ap->a_mutex, NULL, MUTEX_DRIVER, 1375 SBP2_GET_IBLOCK_COOKIE(tp)); 1376 cv_init(&ap->a_cv, NULL, CV_DRIVER, NULL); 1377 1378 #ifndef __lock_lint 1379 ap->a_state = SBP2_AGENT_STATE_RESET; 1380 #endif 1381 1382 return (SBP2_SUCCESS); 1383 } 1384 1385 1386 static void 1387 sbp2_agent_fini(sbp2_agent_t *ap) 1388 { 1389 sbp2_tgt_t *tp = ap->a_tgt; 1390 1391 /* free bus commands */ 1392 if (ap->a_cmd != NULL) { 1393 SBP2_FREE_CMD(tp, ap->a_cmd); 1394 } 1395 if (ap->a_cmd_data != NULL) { 1396 freeb(ap->a_cmd_data); 1397 } 1398 cv_destroy(&ap->a_cv); 1399 mutex_destroy(&ap->a_mutex); 1400 } 1401 1402 1403 static void 1404 sbp2_agent_acquire_locked(sbp2_agent_t *ap) 1405 { 1406 while (ap->a_acquired) { 1407 cv_wait(&ap->a_cv, &ap->a_mutex); 1408 } 1409 ap->a_acquired = B_TRUE; 1410 } 1411 1412 1413 static void 1414 sbp2_agent_release_locked(sbp2_agent_t *ap) 1415 { 1416 ap->a_acquired = B_FALSE; 1417 cv_signal(&ap->a_cv); /* wake next waiter */ 1418 } 1419 1420 1421 static void 1422 sbp2_agent_acquire(sbp2_agent_t *ap) 1423 { 1424 mutex_enter(&ap->a_mutex); 1425 sbp2_agent_acquire_locked(ap); 1426 mutex_exit(&ap->a_mutex); 1427 } 1428 1429 1430 static void 1431 sbp2_agent_release(sbp2_agent_t *ap) 1432 { 1433 mutex_enter(&ap->a_mutex); 1434 sbp2_agent_release_locked(ap); 1435 mutex_exit(&ap->a_mutex); 1436 } 1437 1438 1439 static int 1440 sbp2_agent_keepalive(sbp2_agent_t *ap, int *berr) 1441 { 1442 boolean_t acquired; 1443 int ret = SBP2_SUCCESS; 1444 1445 ASSERT(mutex_owned(&ap->a_mutex)); 1446 1447 if (ap->a_state == SBP2_AGENT_STATE_DEAD) { 1448 acquired = ap->a_acquired; 1449 if (!acquired) { 1450 sbp2_agent_acquire_locked(ap); 1451 } 1452 1453 mutex_exit(&ap->a_mutex); 1454 ret = sbp2_agent_reset(ap, berr); 1455 mutex_enter(&ap->a_mutex); 1456 1457 if (!acquired) { 1458 sbp2_agent_release_locked(ap); 1459 } 1460 } 1461 1462 return (ret); 1463 } 1464 1465 #ifndef __lock_lint 1466 static int 1467 sbp2_agent_doorbell(sbp2_agent_t *ap, int *berr) 1468 { 1469 return (SBP2_WQ(ap->a_tgt, ap->a_cmd, ap->a_reg_doorbell, 0, berr)); 1470 } 1471 #endif 1472 1473 /* 1474 * write into ORB_POINTER register and make sure it reached target 1475 * 1476 * From E.2: "If no acknowledgement is received by the initiator after a write 1477 * to the ORB_POINTER register, the initiator should not retry the write. 1478 * The recommended method for error recovery is a write to the AGENT_RESET 1479 * register." So we can retry, but not in case of timeout. 1480 */ 1481 static int 1482 sbp2_agent_write_orbp(sbp2_agent_t *ap, uint64_t baddr, int *berr) 1483 { 1484 int i = 0; 1485 int ret; 1486 1487 SBP2_ORBP_SET(ap->a_cmd_data->b_rptr, baddr); 1488 ap->a_cmd_data->b_wptr = ap->a_cmd_data->b_rptr + 8; 1489 1490 for (;;) { 1491 ap->a_tgt->t_stat.stat_agent_worbp++; 1492 if ((ret = SBP2_WB(ap->a_tgt, ap->a_cmd, ap->a_reg_orbp, 1493 ap->a_cmd_data, 8, berr)) == SBP2_SUCCESS) { 1494 return (ret); 1495 } 1496 ap->a_tgt->t_stat.stat_agent_worbp_fail++; 1497 1498 if ((ret == SBP2_ETIMEOUT) || 1499 (++i > sbp2_write_orbp_nretries)) { 1500 break; 1501 } 1502 if (sbp2_write_orbp_delay > 0) { 1503 drv_usecwait(sbp2_write_orbp_delay); 1504 } 1505 } 1506 1507 return (ret); 1508 } 1509 1510 1511 /* 1512 * reset fetch agent by writing into AGENT_RESET register 1513 */ 1514 static int 1515 sbp2_agent_reset(sbp2_agent_t *ap, int *berr) 1516 { 1517 int i = 0; 1518 int ret; 1519 1520 for (;;) { 1521 ap->a_tgt->t_stat.stat_agent_wreset++; 1522 if ((ret = SBP2_WQ(ap->a_tgt, ap->a_cmd, ap->a_reg_agent_reset, 1523 0, berr)) == SBP2_SUCCESS) { 1524 mutex_enter(&ap->a_mutex); 1525 ap->a_state = SBP2_AGENT_STATE_RESET; 1526 mutex_exit(&ap->a_mutex); 1527 break; 1528 } 1529 1530 ap->a_tgt->t_stat.stat_agent_wreset_fail++; 1531 if (++i > sbp2_submit_reset_nretries) { 1532 break; 1533 } 1534 if (sbp2_submit_reset_delay > 0) { 1535 drv_usecwait(sbp2_submit_reset_delay); 1536 } 1537 } 1538 return (ret); 1539 } 1540 1541 /* 1542 * 1543 * --- callbacks and timeouts 1544 * 1545 */ 1546 /* 1547 * Status FIFO callback for mgt ORB's. 1548 */ 1549 /*ARGSUSED*/ 1550 static void 1551 sbp2_mgt_status_fifo_wb_cb(sbp2_bus_buf_t *buf, void *reqh, mblk_t **bpp) 1552 { 1553 sbp2_tgt_t *tp = buf->bb_sbp2_priv; 1554 int len; 1555 sbp2_status_t *st; 1556 uint64_t orbp; 1557 1558 len = MBLKL(*bpp); 1559 1560 /* 8 bytes minimum */ 1561 if (len < 8) { 1562 SBP2_BUF_WR_DONE(tp, buf, reqh, SBP2_BUS_BUF_ELENGTH); 1563 tp->t_stat.stat_status_short++; 1564 return; 1565 } 1566 1567 /* convert 2-quadlet header from BE to native endianness */ 1568 st = (sbp2_status_t *)(*bpp)->b_rptr; 1569 SBP2_SWAP16_1(st->st_orb_offset_hi); 1570 SBP2_SWAP32_1(st->st_orb_offset_lo); 1571 orbp = ((uint64_t)st->st_orb_offset_hi << 32) | st->st_orb_offset_lo; 1572 1573 if (orbp != tp->t_mgt_orb_buf.bb_baddr) { 1574 SBP2_BUF_WR_DONE(tp, buf, reqh, SBP2_BUS_BUF_FAILURE); 1575 tp->t_stat.stat_status_mgt_notask++; 1576 return; 1577 } 1578 1579 /* make a local copy of status block */ 1580 bzero(&tp->t_mgt_status, sizeof (sbp2_status_t)); 1581 bcopy((*bpp)->b_rptr, &tp->t_mgt_status, len); 1582 1583 SBP2_BUF_WR_DONE(tp, buf, reqh, SBP2_BUS_BUF_SUCCESS); 1584 1585 /* wake up waiter */ 1586 mutex_enter(&tp->t_mutex); 1587 tp->t_mgt_status_rcvd = B_TRUE; 1588 cv_signal(&tp->t_mgt_status_cv); 1589 mutex_exit(&tp->t_mutex); 1590 } 1591 1592 static void 1593 sbp2_task_timeout(void *arg) 1594 { 1595 sbp2_task_t *task = arg; 1596 sbp2_ses_t *sp = task->ts_ses; 1597 sbp2_agent_t *ap = &sp->s_agent; 1598 1599 mutex_enter(&ap->a_mutex); 1600 1601 /* cancelled? */ 1602 if (task->ts_timeout_id == 0) { 1603 mutex_exit(&ap->a_mutex); 1604 return; 1605 } 1606 task->ts_timeout_id = 0; 1607 task->ts_time_comp = gethrtime(); 1608 1609 /* avoid race with other callbacks */ 1610 if (task->ts_state != SBP2_TASK_PEND) { 1611 mutex_exit(&ap->a_mutex); 1612 return; 1613 } 1614 1615 if (task == ap->a_active_task) { 1616 ap->a_active_task = NULL; 1617 } 1618 task->ts_error = SBP2_TASK_ERR_TIMEOUT; 1619 task->ts_state = SBP2_TASK_COMP; 1620 1621 /* we mark agent DEAD so it's reset before next task is submitted */ 1622 ap->a_state = SBP2_AGENT_STATE_DEAD; 1623 sp->s_tgt->t_stat.stat_status_dead++; 1624 mutex_exit(&ap->a_mutex); 1625 1626 sp->s_status_cb(sp->s_status_cb_arg, task); 1627 } 1628 1629 /* 1630 * Status FIFO callback for command ORB's. Also used for login ORB. 1631 */ 1632 /*ARGSUSED*/ 1633 static void 1634 sbp2_status_fifo_wb_cb(sbp2_bus_buf_t *buf, void *reqh, mblk_t **bpp) 1635 { 1636 sbp2_ses_t *sp = buf->bb_sbp2_priv; 1637 sbp2_tgt_t *tp = sp->s_tgt; 1638 sbp2_agent_t *ap = &sp->s_agent; 1639 int len; 1640 sbp2_status_t *st; 1641 uint8_t src; 1642 uint64_t orbp; 1643 sbp2_task_t *task; 1644 timeout_id_t timeout_id; 1645 1646 len = MBLKL(*bpp); 1647 1648 /* 8 bytes minimum */ 1649 if (len < 8) { 1650 SBP2_BUF_WR_DONE(tp, buf, reqh, SBP2_BUS_BUF_ELENGTH); 1651 tp->t_stat.stat_status_short++; 1652 return; 1653 } 1654 1655 /* convert 2-quadlet header from BE32 to native endianness */ 1656 st = (sbp2_status_t *)(*bpp)->b_rptr; 1657 SBP2_SWAP16_1(st->st_orb_offset_hi); 1658 SBP2_SWAP32_1(st->st_orb_offset_lo); 1659 1660 orbp = ((uint64_t)st->st_orb_offset_hi << 32) | st->st_orb_offset_lo; 1661 1662 /* login ORB status? */ 1663 if (orbp == tp->t_mgt_orb_buf.bb_baddr) { 1664 bzero(&tp->t_mgt_status, sizeof (sbp2_status_t)); 1665 bcopy((*bpp)->b_rptr, &tp->t_mgt_status, len); 1666 1667 SBP2_BUF_WR_DONE(tp, buf, reqh, SBP2_BUS_BUF_SUCCESS); 1668 1669 /* wake up waiter */ 1670 mutex_enter(&tp->t_mutex); 1671 tp->t_mgt_status_rcvd = B_TRUE; 1672 cv_signal(&tp->t_mgt_status_cv); 1673 mutex_exit(&tp->t_mutex); 1674 return; 1675 } 1676 1677 /* dismiss unsolicited status */ 1678 src = st->st_param & SBP2_ST_SRC; 1679 if (src == SBP2_ST_SRC_UNSOLICITED) { 1680 SBP2_BUF_WR_DONE(tp, buf, reqh, SBP2_BUS_BUF_FAILURE); 1681 tp->t_stat.stat_status_unsolicited++; 1682 return; 1683 } 1684 1685 /* find task corresponding to this ORB pointer */ 1686 if ((task = sbp2_ses_orbp2task(sp, orbp)) == NULL) { 1687 SBP2_BUF_WR_DONE(tp, buf, reqh, SBP2_BUS_BUF_FAILURE); 1688 tp->t_stat.stat_status_notask++; 1689 return; 1690 } 1691 1692 /* 1693 * Copy status block into a local buffer. 1694 * 1695 * Note: (ref: B.2) "SBP-2 permits the return of a status block between 1696 * two and eight quadlets in length. When a truncated status block 1697 * is stored, the omited quadlets shall be interpreted as if zero 1698 * values were stored." 1699 */ 1700 bzero(&task->ts_status, sizeof (sbp2_status_t)); 1701 bcopy((*bpp)->b_rptr, &task->ts_status, len); 1702 1703 SBP2_BUF_WR_DONE(tp, buf, reqh, SBP2_BUS_BUF_SUCCESS); 1704 1705 mutex_enter(&ap->a_mutex); 1706 1707 if ((timeout_id = task->ts_timeout_id) != 0) { 1708 task->ts_timeout_id = 0; 1709 (void) untimeout(timeout_id); 1710 } 1711 1712 /* determine agent state */ 1713 if (st->st_param & SBP2_ST_DEAD) { 1714 ap->a_state = SBP2_AGENT_STATE_DEAD; 1715 tp->t_stat.stat_status_dead++; 1716 } 1717 1718 /* avoid race with other callbacks */ 1719 if (task->ts_state != SBP2_TASK_PEND) { 1720 mutex_exit(&ap->a_mutex); 1721 return; 1722 } 1723 1724 if (task == ap->a_active_task) { 1725 ap->a_active_task = NULL; 1726 } 1727 task->ts_error = SBP2_TASK_ERR_NONE; 1728 task->ts_state = SBP2_TASK_COMP; 1729 1730 mutex_exit(&ap->a_mutex); 1731 1732 sp->s_status_cb(sp->s_status_cb_arg, task); /* notify the driver */ 1733 } 1734 1735 /* 1736 * 1737 * --- other 1738 * 1739 * since mgt agent is shared between LUNs and login sessions, 1740 * it is safer to serialize mgt requests 1741 */ 1742 static void 1743 sbp2_mgt_agent_acquire(sbp2_tgt_t *tp) 1744 { 1745 mutex_enter(&tp->t_mutex); 1746 while (tp->t_mgt_agent_acquired) { 1747 cv_wait(&tp->t_mgt_agent_cv, &tp->t_mutex); 1748 } 1749 tp->t_mgt_agent_acquired = B_TRUE; 1750 mutex_exit(&tp->t_mutex); 1751 } 1752 1753 static void 1754 sbp2_mgt_agent_release(sbp2_tgt_t *tp) 1755 { 1756 mutex_enter(&tp->t_mutex); 1757 tp->t_mgt_agent_acquired = B_FALSE; 1758 cv_signal(&tp->t_mgt_agent_cv); /* wake next waiter */ 1759 mutex_exit(&tp->t_mutex); 1760 } 1761