ctl_frontend_internal.c revision 256217
1/*- 2 * Copyright (c) 2004, 2005 Silicon Graphics International Corp. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions, and the following disclaimer, 10 * without modification. 11 * 2. Redistributions in binary form must reproduce at minimum a disclaimer 12 * substantially similar to the "NO WARRANTY" disclaimer below 13 * ("Disclaimer") and any redistribution must be conditioned upon 14 * including a substantially similar Disclaimer requirement for further 15 * binary redistribution. 16 * 17 * NO WARRANTY 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 26 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 27 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 * POSSIBILITY OF SUCH DAMAGES. 29 * 30 * $Id: //depot/users/kenm/FreeBSD-test2/sys/cam/ctl/ctl_frontend_internal.c#5 $ 31 */ 32/* 33 * CTL kernel internal frontend target driver. This allows kernel-level 34 * clients to send commands into CTL. 35 * 36 * This has elements of a FETD (e.g. it has to set tag numbers, initiator, 37 * port, target, and LUN) and elements of an initiator (LUN discovery and 38 * probing, error recovery, command initiation). Even though this has some 39 * initiator type elements, this is not intended to be a full fledged 40 * initiator layer. It is only intended to send a limited number of 41 * commands to a well known target layer. 42 * 43 * To be able to fulfill the role of a full initiator layer, it would need 44 * a whole lot more functionality. 45 * 46 * Author: Ken Merry <ken@FreeBSD.org> 47 * 48 */ 49 50#include <sys/cdefs.h> 51__FBSDID("$FreeBSD: stable/9/sys/cam/ctl/ctl_frontend_internal.c 256217 2013-10-09 19:02:59Z mav $"); 52 53#include <sys/param.h> 54#include <sys/systm.h> 55#include <sys/kernel.h> 56#include <sys/types.h> 57#include <sys/malloc.h> 58#include <sys/module.h> 59#include <sys/lock.h> 60#include <sys/mutex.h> 61#include <sys/condvar.h> 62#include <sys/queue.h> 63#include <sys/sbuf.h> 64#include <sys/sysctl.h> 65#include <cam/scsi/scsi_all.h> 66#include <cam/scsi/scsi_da.h> 67#include <cam/ctl/ctl_io.h> 68#include <cam/ctl/ctl.h> 69#include <cam/ctl/ctl_frontend.h> 70#include <cam/ctl/ctl_frontend_internal.h> 71#include <cam/ctl/ctl_backend.h> 72#include <cam/ctl/ctl_ioctl.h> 73#include <cam/ctl/ctl_util.h> 74#include <cam/ctl/ctl_ha.h> 75#include <cam/ctl/ctl_private.h> 76#include <cam/ctl/ctl_mem_pool.h> 77#include <cam/ctl/ctl_debug.h> 78#include <cam/ctl/ctl_scsi_all.h> 79#include <cam/ctl/ctl_error.h> 80 81/* 82 * Task structure: 83 * - overall metatask, different potential metatask types (e.g. forced 84 * shutdown, gentle shutdown) 85 * - forced shutdown metatask: 86 * - states: report luns, pending, done? 87 * - list of luns pending, with the relevant I/O for that lun attached. 88 * This would allow moving ahead on LUNs with no errors, and going 89 * into error recovery on LUNs with problems. Per-LUN states might 90 * include inquiry, stop/offline, done. 91 * 92 * Use LUN enable for LUN list instead of getting it manually? We'd still 93 * need inquiry data for each LUN. 94 * 95 * How to handle processor LUN w.r.t. found/stopped counts? 96 */ 97#ifdef oldapi 98typedef enum { 99 CFI_TASK_NONE, 100 CFI_TASK_SHUTDOWN, 101 CFI_TASK_STARTUP 102} cfi_tasktype; 103 104struct cfi_task_startstop { 105 int total_luns; 106 int luns_complete; 107 int luns_failed; 108 cfi_cb_t callback; 109 void *callback_arg; 110 /* XXX KDM add more fields here */ 111}; 112 113union cfi_taskinfo { 114 struct cfi_task_startstop startstop; 115}; 116 117struct cfi_metatask { 118 cfi_tasktype tasktype; 119 cfi_mt_status status; 120 union cfi_taskinfo taskinfo; 121 struct ctl_mem_element *element; 122 void *cfi_context; 123 STAILQ_ENTRY(cfi_metatask) links; 124}; 125#endif 126 127typedef enum { 128 CFI_ERR_RETRY = 0x000, 129 CFI_ERR_FAIL = 0x001, 130 CFI_ERR_LUN_RESET = 0x002, 131 CFI_ERR_MASK = 0x0ff, 132 CFI_ERR_NO_DECREMENT = 0x100 133} cfi_error_action; 134 135typedef enum { 136 CFI_ERR_SOFT, 137 CFI_ERR_HARD 138} cfi_error_policy; 139 140typedef enum { 141 CFI_LUN_INQUIRY, 142 CFI_LUN_READCAPACITY, 143 CFI_LUN_READCAPACITY_16, 144 CFI_LUN_READY 145} cfi_lun_state; 146 147struct cfi_lun { 148 struct ctl_id target_id; 149 int lun_id; 150 struct scsi_inquiry_data inq_data; 151 uint64_t num_blocks; 152 uint32_t blocksize; 153 int blocksize_powerof2; 154 uint32_t cur_tag_num; 155 cfi_lun_state state; 156 struct ctl_mem_element *element; 157 struct cfi_softc *softc; 158 STAILQ_HEAD(, cfi_lun_io) io_list; 159 STAILQ_ENTRY(cfi_lun) links; 160}; 161 162struct cfi_lun_io { 163 struct cfi_lun *lun; 164 struct cfi_metatask *metatask; 165 cfi_error_policy policy; 166 void (*done_function)(union ctl_io *io); 167 union ctl_io *ctl_io; 168 struct cfi_lun_io *orig_lun_io; 169 STAILQ_ENTRY(cfi_lun_io) links; 170}; 171 172typedef enum { 173 CFI_NONE = 0x00, 174 CFI_ONLINE = 0x01, 175} cfi_flags; 176 177struct cfi_softc { 178 struct ctl_frontend fe; 179 char fe_name[40]; 180 struct mtx lock; 181 cfi_flags flags; 182 STAILQ_HEAD(, cfi_lun) lun_list; 183 STAILQ_HEAD(, cfi_metatask) metatask_list; 184 struct ctl_mem_pool lun_pool; 185 struct ctl_mem_pool metatask_pool; 186}; 187 188MALLOC_DEFINE(M_CTL_CFI, "ctlcfi", "CTL CFI"); 189 190static struct cfi_softc fetd_internal_softc; 191extern int ctl_disable; 192 193int cfi_init(void); 194void cfi_shutdown(void) __unused; 195static void cfi_online(void *arg); 196static void cfi_offline(void *arg); 197static int cfi_targ_enable(void *arg, struct ctl_id targ_id); 198static int cfi_targ_disable(void *arg, struct ctl_id targ_id); 199static int cfi_lun_enable(void *arg, struct ctl_id target_id, int lun_id); 200static int cfi_lun_disable(void *arg, struct ctl_id target_id, int lun_id); 201static void cfi_datamove(union ctl_io *io); 202static cfi_error_action cfi_checkcond_parse(union ctl_io *io, 203 struct cfi_lun_io *lun_io); 204static cfi_error_action cfi_error_parse(union ctl_io *io, 205 struct cfi_lun_io *lun_io); 206static void cfi_init_io(union ctl_io *io, struct cfi_lun *lun, 207 struct cfi_metatask *metatask, cfi_error_policy policy, 208 int retries, struct cfi_lun_io *orig_lun_io, 209 void (*done_function)(union ctl_io *io)); 210static void cfi_done(union ctl_io *io); 211static void cfi_lun_probe_done(union ctl_io *io); 212static void cfi_lun_probe(struct cfi_lun *lun, int have_lock); 213static void cfi_metatask_done(struct cfi_softc *softc, 214 struct cfi_metatask *metatask); 215static void cfi_metatask_bbr_errorparse(struct cfi_metatask *metatask, 216 union ctl_io *io); 217static void cfi_metatask_io_done(union ctl_io *io); 218static void cfi_err_recovery_done(union ctl_io *io); 219static void cfi_lun_io_done(union ctl_io *io); 220 221static int cfi_module_event_handler(module_t, int /*modeventtype_t*/, void *); 222 223static moduledata_t cfi_moduledata = { 224 "ctlcfi", 225 cfi_module_event_handler, 226 NULL 227}; 228 229DECLARE_MODULE(ctlcfi, cfi_moduledata, SI_SUB_CONFIGURE, SI_ORDER_FOURTH); 230MODULE_VERSION(ctlcfi, 1); 231MODULE_DEPEND(ctlcfi, ctl, 1, 1, 1); 232 233int 234cfi_init(void) 235{ 236 struct cfi_softc *softc; 237 struct ctl_frontend *fe; 238 int retval; 239 240 softc = &fetd_internal_softc; 241 242 fe = &softc->fe; 243 244 retval = 0; 245 246 /* If we're disabled, don't initialize */ 247 if (ctl_disable != 0) 248 return (0); 249 250 if (sizeof(struct cfi_lun_io) > CTL_PORT_PRIV_SIZE) { 251 printf("%s: size of struct cfi_lun_io %zd > " 252 "CTL_PORT_PRIV_SIZE %d\n", __func__, 253 sizeof(struct cfi_lun_io), 254 CTL_PORT_PRIV_SIZE); 255 } 256 memset(softc, 0, sizeof(*softc)); 257 258 mtx_init(&softc->lock, "CTL frontend mutex", NULL, MTX_DEF); 259 softc->flags |= CTL_FLAG_MASTER_SHELF; 260 261 STAILQ_INIT(&softc->lun_list); 262 STAILQ_INIT(&softc->metatask_list); 263 sprintf(softc->fe_name, "CTL internal"); 264 fe->port_type = CTL_PORT_INTERNAL; 265 fe->num_requested_ctl_io = 100; 266 fe->port_name = softc->fe_name; 267 fe->port_online = cfi_online; 268 fe->port_offline = cfi_offline; 269 fe->onoff_arg = softc; 270 fe->targ_enable = cfi_targ_enable; 271 fe->targ_disable = cfi_targ_disable; 272 fe->lun_enable = cfi_lun_enable; 273 fe->lun_disable = cfi_lun_disable; 274 fe->targ_lun_arg = softc; 275 fe->fe_datamove = cfi_datamove; 276 fe->fe_done = cfi_done; 277 fe->max_targets = 15; 278 fe->max_target_id = 15; 279 280 if (ctl_frontend_register(fe, (softc->flags & CTL_FLAG_MASTER_SHELF)) != 0) 281 { 282 printf("%s: internal frontend registration failed\n", __func__); 283 retval = 1; 284 goto bailout; 285 } 286 287 if (ctl_init_mem_pool(&softc->lun_pool, 288 sizeof(struct cfi_lun), 289 CTL_MEM_POOL_PERM_GROW, /*grow_inc*/ 3, 290 /* initial_pool_size */ CTL_MAX_LUNS) != 0) { 291 printf("%s: can't initialize LUN memory pool\n", __func__); 292 retval = 1; 293 goto bailout_error; 294 } 295 296 if (ctl_init_mem_pool(&softc->metatask_pool, 297 sizeof(struct cfi_metatask), 298 CTL_MEM_POOL_PERM_GROW, /*grow_inc*/ 3, 299 /*initial_pool_size*/ 10) != 0) { 300 printf("%s: can't initialize metatask memory pool\n", __func__); 301 retval = 2; 302 goto bailout_error; 303 } 304bailout: 305 306 return (0); 307 308bailout_error: 309 310 switch (retval) { 311 case 3: 312 ctl_shrink_mem_pool(&softc->metatask_pool); 313 /* FALLTHROUGH */ 314 case 2: 315 ctl_shrink_mem_pool(&softc->lun_pool); 316 /* FALLTHROUGH */ 317 case 1: 318 ctl_frontend_deregister(fe); 319 break; 320 default: 321 break; 322 } 323 324 return (ENOMEM); 325} 326 327void 328cfi_shutdown(void) 329{ 330 struct cfi_softc *softc; 331 332 softc = &fetd_internal_softc; 333 334 /* 335 * XXX KDM need to clear out any I/O pending on each LUN. 336 */ 337 if (ctl_frontend_deregister(&softc->fe) != 0) 338 printf("%s: ctl_frontend_deregister() failed\n", __func__); 339 340 if (ctl_shrink_mem_pool(&softc->lun_pool) != 0) 341 printf("%s: error shrinking LUN pool\n", __func__); 342 343 if (ctl_shrink_mem_pool(&softc->metatask_pool) != 0) 344 printf("%s: error shrinking LUN pool\n", __func__); 345} 346 347static int 348cfi_module_event_handler(module_t mod, int what, void *arg) 349{ 350 351 switch (what) { 352 case MOD_LOAD: 353 return (cfi_init()); 354 case MOD_UNLOAD: 355 return (EBUSY); 356 default: 357 return (EOPNOTSUPP); 358 } 359} 360 361static void 362cfi_online(void *arg) 363{ 364 struct cfi_softc *softc; 365 struct cfi_lun *lun; 366 367 softc = (struct cfi_softc *)arg; 368 369 softc->flags |= CFI_ONLINE; 370 371 /* 372 * Go through and kick off the probe for each lun. Should we check 373 * the LUN flags here to determine whether or not to probe it? 374 */ 375 mtx_lock(&softc->lock); 376 STAILQ_FOREACH(lun, &softc->lun_list, links) 377 cfi_lun_probe(lun, /*have_lock*/ 1); 378 mtx_unlock(&softc->lock); 379} 380 381static void 382cfi_offline(void *arg) 383{ 384 struct cfi_softc *softc; 385 386 softc = (struct cfi_softc *)arg; 387 388 softc->flags &= ~CFI_ONLINE; 389} 390 391static int 392cfi_targ_enable(void *arg, struct ctl_id targ_id) 393{ 394 return (0); 395} 396 397static int 398cfi_targ_disable(void *arg, struct ctl_id targ_id) 399{ 400 return (0); 401} 402 403static int 404cfi_lun_enable(void *arg, struct ctl_id target_id, int lun_id) 405{ 406 struct ctl_mem_element *element; 407 struct cfi_softc *softc; 408 struct cfi_lun *lun; 409 int found; 410 411 softc = (struct cfi_softc *)arg; 412 413 found = 0; 414 mtx_lock(&softc->lock); 415 STAILQ_FOREACH(lun, &softc->lun_list, links) { 416 if ((lun->target_id.id == target_id.id) 417 && (lun->lun_id == lun_id)) { 418 found = 1; 419 break; 420 } 421 } 422 mtx_unlock(&softc->lock); 423 424 /* 425 * If we already have this target/LUN, there is no reason to add 426 * it to our lists again. 427 */ 428 if (found != 0) 429 return (0); 430 431 element = ctl_alloc_mem_element(&softc->lun_pool, /*can_wait*/ 0); 432 433 if (element == NULL) { 434 printf("%s: unable to allocate LUN structure\n", __func__); 435 return (1); 436 } 437 438 lun = (struct cfi_lun *)element->bytes; 439 440 lun->element = element; 441 lun->target_id = target_id; 442 lun->lun_id = lun_id; 443 lun->cur_tag_num = 0; 444 lun->state = CFI_LUN_INQUIRY; 445 lun->softc = softc; 446 STAILQ_INIT(&lun->io_list); 447 448 mtx_lock(&softc->lock); 449 STAILQ_INSERT_TAIL(&softc->lun_list, lun, links); 450 mtx_unlock(&softc->lock); 451 452 cfi_lun_probe(lun, /*have_lock*/ 0); 453 454 return (0); 455} 456 457static int 458cfi_lun_disable(void *arg, struct ctl_id target_id, int lun_id) 459{ 460 struct cfi_softc *softc; 461 struct cfi_lun *lun; 462 int found; 463 464 softc = (struct cfi_softc *)arg; 465 466 found = 0; 467 468 /* 469 * XXX KDM need to do an invalidate and then a free when any 470 * pending I/O has completed. Or do we? CTL won't free a LUN 471 * while any I/O is pending. So we won't get this notification 472 * unless any I/O we have pending on a LUN has completed. 473 */ 474 mtx_lock(&softc->lock); 475 STAILQ_FOREACH(lun, &softc->lun_list, links) { 476 if ((lun->target_id.id == target_id.id) 477 && (lun->lun_id == lun_id)) { 478 found = 1; 479 break; 480 } 481 } 482 if (found != 0) 483 STAILQ_REMOVE(&softc->lun_list, lun, cfi_lun, links); 484 485 mtx_unlock(&softc->lock); 486 487 if (found == 0) { 488 printf("%s: can't find target %ju lun %d\n", __func__, 489 (uintmax_t)target_id.id, lun_id); 490 return (1); 491 } 492 493 ctl_free_mem_element(lun->element); 494 495 return (0); 496} 497 498/* 499 * XXX KDM run this inside a thread, or inside the caller's context? 500 */ 501static void 502cfi_datamove(union ctl_io *io) 503{ 504 struct ctl_sg_entry *ext_sglist, *kern_sglist; 505 struct ctl_sg_entry ext_entry, kern_entry; 506 int ext_sglen, ext_sg_entries, kern_sg_entries; 507 int ext_sg_start, ext_offset; 508 int len_to_copy, len_copied; 509 int kern_watermark, ext_watermark; 510 int ext_sglist_malloced; 511 struct ctl_scsiio *ctsio; 512 int i, j; 513 514 ext_sglist_malloced = 0; 515 ext_sg_start = 0; 516 ext_offset = 0; 517 ext_sglist = NULL; 518 519 CTL_DEBUG_PRINT(("%s\n", __func__)); 520 521 ctsio = &io->scsiio; 522 523 /* 524 * If this is the case, we're probably doing a BBR read and don't 525 * actually need to transfer the data. This will effectively 526 * bit-bucket the data. 527 */ 528 if (ctsio->ext_data_ptr == NULL) 529 goto bailout; 530 531 /* 532 * To simplify things here, if we have a single buffer, stick it in 533 * a S/G entry and just make it a single entry S/G list. 534 */ 535 if (ctsio->io_hdr.flags & CTL_FLAG_EDPTR_SGLIST) { 536 int len_seen; 537 538 ext_sglen = ctsio->ext_sg_entries * sizeof(*ext_sglist); 539 540 /* 541 * XXX KDM GFP_KERNEL, don't know what the caller's context 542 * is. Need to figure that out. 543 */ 544 ext_sglist = (struct ctl_sg_entry *)malloc(ext_sglen, M_CTL_CFI, 545 M_WAITOK); 546 if (ext_sglist == NULL) { 547 ctl_set_internal_failure(ctsio, 548 /*sks_valid*/ 0, 549 /*retry_count*/ 0); 550 return; 551 } 552 ext_sglist_malloced = 1; 553 if (memcpy(ext_sglist, ctsio->ext_data_ptr, ext_sglen) != 0) { 554 ctl_set_internal_failure(ctsio, 555 /*sks_valid*/ 0, 556 /*retry_count*/ 0); 557 goto bailout; 558 } 559 ext_sg_entries = ctsio->ext_sg_entries; 560 len_seen = 0; 561 for (i = 0; i < ext_sg_entries; i++) { 562 if ((len_seen + ext_sglist[i].len) >= 563 ctsio->ext_data_filled) { 564 ext_sg_start = i; 565 ext_offset = ctsio->ext_data_filled - len_seen; 566 break; 567 } 568 len_seen += ext_sglist[i].len; 569 } 570 } else { 571 ext_sglist = &ext_entry; 572 ext_sglist->addr = ctsio->ext_data_ptr; 573 ext_sglist->len = ctsio->ext_data_len; 574 ext_sg_entries = 1; 575 ext_sg_start = 0; 576 ext_offset = ctsio->ext_data_filled; 577 } 578 579 if (ctsio->kern_sg_entries > 0) { 580 kern_sglist = (struct ctl_sg_entry *)ctsio->kern_data_ptr; 581 kern_sg_entries = ctsio->kern_sg_entries; 582 } else { 583 kern_sglist = &kern_entry; 584 kern_sglist->addr = ctsio->kern_data_ptr; 585 kern_sglist->len = ctsio->kern_data_len; 586 kern_sg_entries = 1; 587 } 588 589 590 kern_watermark = 0; 591 ext_watermark = ext_offset; 592 len_copied = 0; 593 for (i = ext_sg_start, j = 0; 594 i < ext_sg_entries && j < kern_sg_entries;) { 595 uint8_t *ext_ptr, *kern_ptr; 596 597 len_to_copy = ctl_min(ext_sglist[i].len - ext_watermark, 598 kern_sglist[j].len - kern_watermark); 599 600 ext_ptr = (uint8_t *)ext_sglist[i].addr; 601 ext_ptr = ext_ptr + ext_watermark; 602 if (io->io_hdr.flags & CTL_FLAG_BUS_ADDR) { 603 /* 604 * XXX KDM fix this! 605 */ 606 panic("need to implement bus address support"); 607#if 0 608 kern_ptr = bus_to_virt(kern_sglist[j].addr); 609#endif 610 } else 611 kern_ptr = (uint8_t *)kern_sglist[j].addr; 612 kern_ptr = kern_ptr + kern_watermark; 613 614 kern_watermark += len_to_copy; 615 ext_watermark += len_to_copy; 616 617 if ((ctsio->io_hdr.flags & CTL_FLAG_DATA_MASK) == 618 CTL_FLAG_DATA_IN) { 619 CTL_DEBUG_PRINT(("%s: copying %d bytes to user\n", 620 __func__, len_to_copy)); 621 CTL_DEBUG_PRINT(("%s: from %p to %p\n", __func__, 622 kern_ptr, ext_ptr)); 623 memcpy(ext_ptr, kern_ptr, len_to_copy); 624 } else { 625 CTL_DEBUG_PRINT(("%s: copying %d bytes from user\n", 626 __func__, len_to_copy)); 627 CTL_DEBUG_PRINT(("%s: from %p to %p\n", __func__, 628 ext_ptr, kern_ptr)); 629 memcpy(kern_ptr, ext_ptr, len_to_copy); 630 } 631 632 len_copied += len_to_copy; 633 634 if (ext_sglist[i].len == ext_watermark) { 635 i++; 636 ext_watermark = 0; 637 } 638 639 if (kern_sglist[j].len == kern_watermark) { 640 j++; 641 kern_watermark = 0; 642 } 643 } 644 645 ctsio->ext_data_filled += len_copied; 646 647 CTL_DEBUG_PRINT(("%s: ext_sg_entries: %d, kern_sg_entries: %d\n", 648 __func__, ext_sg_entries, kern_sg_entries)); 649 CTL_DEBUG_PRINT(("%s: ext_data_len = %d, kern_data_len = %d\n", 650 __func__, ctsio->ext_data_len, ctsio->kern_data_len)); 651 652 653 /* XXX KDM set residual?? */ 654bailout: 655 656 if (ext_sglist_malloced != 0) 657 free(ext_sglist, M_CTL_CFI); 658 659 io->scsiio.be_move_done(io); 660 661 return; 662} 663 664/* 665 * For any sort of check condition, busy, etc., we just retry. We do not 666 * decrement the retry count for unit attention type errors. These are 667 * normal, and we want to save the retry count for "real" errors. Otherwise, 668 * we could end up with situations where a command will succeed in some 669 * situations and fail in others, depending on whether a unit attention is 670 * pending. Also, some of our error recovery actions, most notably the 671 * LUN reset action, will cause a unit attention. 672 * 673 * We can add more detail here later if necessary. 674 */ 675static cfi_error_action 676cfi_checkcond_parse(union ctl_io *io, struct cfi_lun_io *lun_io) 677{ 678 cfi_error_action error_action; 679 int error_code, sense_key, asc, ascq; 680 681 /* 682 * Default to retrying the command. 683 */ 684 error_action = CFI_ERR_RETRY; 685 686 scsi_extract_sense_len(&io->scsiio.sense_data, 687 io->scsiio.sense_len, 688 &error_code, 689 &sense_key, 690 &asc, 691 &ascq, 692 /*show_errors*/ 1); 693 694 switch (error_code) { 695 case SSD_DEFERRED_ERROR: 696 case SSD_DESC_DEFERRED_ERROR: 697 error_action |= CFI_ERR_NO_DECREMENT; 698 break; 699 case SSD_CURRENT_ERROR: 700 case SSD_DESC_CURRENT_ERROR: 701 default: { 702 switch (sense_key) { 703 case SSD_KEY_UNIT_ATTENTION: 704 error_action |= CFI_ERR_NO_DECREMENT; 705 break; 706 case SSD_KEY_HARDWARE_ERROR: 707 /* 708 * This is our generic "something bad happened" 709 * error code. It often isn't recoverable. 710 */ 711 if ((asc == 0x44) && (ascq == 0x00)) 712 error_action = CFI_ERR_FAIL; 713 break; 714 case SSD_KEY_NOT_READY: 715 /* 716 * If the LUN is powered down, there likely isn't 717 * much point in retrying right now. 718 */ 719 if ((asc == 0x04) && (ascq == 0x02)) 720 error_action = CFI_ERR_FAIL; 721 /* 722 * If the LUN is offline, there probably isn't much 723 * point in retrying, either. 724 */ 725 if ((asc == 0x04) && (ascq == 0x03)) 726 error_action = CFI_ERR_FAIL; 727 break; 728 } 729 } 730 } 731 732 return (error_action); 733} 734 735static cfi_error_action 736cfi_error_parse(union ctl_io *io, struct cfi_lun_io *lun_io) 737{ 738 cfi_error_action error_action; 739 740 error_action = CFI_ERR_RETRY; 741 742 switch (io->io_hdr.io_type) { 743 case CTL_IO_SCSI: 744 switch (io->io_hdr.status & CTL_STATUS_MASK) { 745 case CTL_SCSI_ERROR: 746 switch (io->scsiio.scsi_status) { 747 case SCSI_STATUS_RESERV_CONFLICT: 748 /* 749 * For a reservation conflict, we'll usually 750 * want the hard error recovery policy, so 751 * we'll reset the LUN. 752 */ 753 if (lun_io->policy == CFI_ERR_HARD) 754 error_action = 755 CFI_ERR_LUN_RESET; 756 else 757 error_action = 758 CFI_ERR_RETRY; 759 break; 760 case SCSI_STATUS_CHECK_COND: 761 default: 762 error_action = cfi_checkcond_parse(io, lun_io); 763 break; 764 } 765 break; 766 default: 767 error_action = CFI_ERR_RETRY; 768 break; 769 } 770 break; 771 case CTL_IO_TASK: 772 /* 773 * In theory task management commands shouldn't fail... 774 */ 775 error_action = CFI_ERR_RETRY; 776 break; 777 default: 778 printf("%s: invalid ctl_io type %d\n", __func__, 779 io->io_hdr.io_type); 780 panic("%s: invalid ctl_io type %d\n", __func__, 781 io->io_hdr.io_type); 782 break; 783 } 784 785 return (error_action); 786} 787 788static void 789cfi_init_io(union ctl_io *io, struct cfi_lun *lun, 790 struct cfi_metatask *metatask, cfi_error_policy policy, int retries, 791 struct cfi_lun_io *orig_lun_io, 792 void (*done_function)(union ctl_io *io)) 793{ 794 struct cfi_lun_io *lun_io; 795 796 io->io_hdr.nexus.initid.id = 7; 797 io->io_hdr.nexus.targ_port = lun->softc->fe.targ_port; 798 io->io_hdr.nexus.targ_target.id = lun->target_id.id; 799 io->io_hdr.nexus.targ_lun = lun->lun_id; 800 io->io_hdr.retries = retries; 801 lun_io = (struct cfi_lun_io *)io->io_hdr.port_priv; 802 io->io_hdr.ctl_private[CTL_PRIV_FRONTEND].ptr = lun_io; 803 lun_io->lun = lun; 804 lun_io->metatask = metatask; 805 lun_io->ctl_io = io; 806 lun_io->policy = policy; 807 lun_io->orig_lun_io = orig_lun_io; 808 lun_io->done_function = done_function; 809 /* 810 * We only set the tag number for SCSI I/Os. For task management 811 * commands, the tag number is only really needed for aborts, so 812 * the caller can set it if necessary. 813 */ 814 switch (io->io_hdr.io_type) { 815 case CTL_IO_SCSI: 816 io->scsiio.tag_num = lun->cur_tag_num++; 817 break; 818 case CTL_IO_TASK: 819 default: 820 break; 821 } 822} 823 824static void 825cfi_done(union ctl_io *io) 826{ 827 struct cfi_lun_io *lun_io; 828 struct cfi_softc *softc; 829 struct cfi_lun *lun; 830 831 lun_io = (struct cfi_lun_io *) 832 io->io_hdr.ctl_private[CTL_PRIV_FRONTEND].ptr; 833 834 lun = lun_io->lun; 835 softc = lun->softc; 836 837 /* 838 * Very minimal retry logic. We basically retry if we got an error 839 * back, and the retry count is greater than 0. If we ever want 840 * more sophisticated initiator type behavior, the CAM error 841 * recovery code in ../common might be helpful. 842 */ 843 if (((io->io_hdr.status & CTL_STATUS_MASK) != CTL_SUCCESS) 844 && (io->io_hdr.retries > 0)) { 845 ctl_io_status old_status; 846 cfi_error_action error_action; 847 848 error_action = cfi_error_parse(io, lun_io); 849 850 switch (error_action & CFI_ERR_MASK) { 851 case CFI_ERR_FAIL: 852 goto done; 853 break; /* NOTREACHED */ 854 case CFI_ERR_LUN_RESET: { 855 union ctl_io *new_io; 856 struct cfi_lun_io *new_lun_io; 857 858 new_io = ctl_alloc_io(softc->fe.ctl_pool_ref); 859 if (new_io == NULL) { 860 printf("%s: unable to allocate ctl_io for " 861 "error recovery\n", __func__); 862 goto done; 863 } 864 ctl_zero_io(new_io); 865 866 new_io->io_hdr.io_type = CTL_IO_TASK; 867 new_io->taskio.task_action = CTL_TASK_LUN_RESET; 868 869 cfi_init_io(new_io, 870 /*lun*/ lun_io->lun, 871 /*metatask*/ NULL, 872 /*policy*/ CFI_ERR_SOFT, 873 /*retries*/ 0, 874 /*orig_lun_io*/lun_io, 875 /*done_function*/ cfi_err_recovery_done); 876 877 878 new_lun_io = (struct cfi_lun_io *) 879 new_io->io_hdr.port_priv; 880 881 mtx_lock(&lun->softc->lock); 882 STAILQ_INSERT_TAIL(&lun->io_list, new_lun_io, links); 883 mtx_unlock(&lun->softc->lock); 884 885 io = new_io; 886 break; 887 } 888 case CFI_ERR_RETRY: 889 default: 890 if ((error_action & CFI_ERR_NO_DECREMENT) == 0) 891 io->io_hdr.retries--; 892 break; 893 } 894 895 old_status = io->io_hdr.status; 896 io->io_hdr.status = CTL_STATUS_NONE; 897#if 0 898 io->io_hdr.flags &= ~CTL_FLAG_ALREADY_DONE; 899#endif 900 io->io_hdr.flags &= ~CTL_FLAG_ABORT; 901 io->io_hdr.flags &= ~CTL_FLAG_SENT_2OTHER_SC; 902 903 if (ctl_queue(io) != CTL_RETVAL_COMPLETE) { 904 printf("%s: error returned from ctl_queue()!\n", 905 __func__); 906 io->io_hdr.status = old_status; 907 } else 908 return; 909 } 910done: 911 lun_io->done_function(io); 912} 913 914static void 915cfi_lun_probe_done(union ctl_io *io) 916{ 917 struct cfi_lun *lun; 918 struct cfi_lun_io *lun_io; 919 920 lun_io = (struct cfi_lun_io *) 921 io->io_hdr.ctl_private[CTL_PRIV_FRONTEND].ptr; 922 lun = lun_io->lun; 923 924 switch (lun->state) { 925 case CFI_LUN_INQUIRY: { 926 if ((io->io_hdr.status & CTL_STATUS_MASK) != CTL_SUCCESS) { 927 /* print out something here?? */ 928 printf("%s: LUN %d probe failed because inquiry " 929 "failed\n", __func__, lun->lun_id); 930 ctl_io_error_print(io, NULL); 931 } else { 932 933 if (SID_TYPE(&lun->inq_data) != T_DIRECT) { 934 char path_str[40]; 935 936 lun->state = CFI_LUN_READY; 937 ctl_scsi_path_string(io, path_str, 938 sizeof(path_str)); 939 printf("%s", path_str); 940 scsi_print_inquiry(&lun->inq_data); 941 } else { 942 lun->state = CFI_LUN_READCAPACITY; 943 cfi_lun_probe(lun, /*have_lock*/ 0); 944 } 945 } 946 mtx_lock(&lun->softc->lock); 947 STAILQ_REMOVE(&lun->io_list, lun_io, cfi_lun_io, links); 948 mtx_unlock(&lun->softc->lock); 949 ctl_free_io(io); 950 break; 951 } 952 case CFI_LUN_READCAPACITY: 953 case CFI_LUN_READCAPACITY_16: { 954 uint64_t maxlba; 955 uint32_t blocksize; 956 957 maxlba = 0; 958 blocksize = 0; 959 960 if ((io->io_hdr.status & CTL_STATUS_MASK) != CTL_SUCCESS) { 961 printf("%s: LUN %d probe failed because READ CAPACITY " 962 "failed\n", __func__, lun->lun_id); 963 ctl_io_error_print(io, NULL); 964 } else { 965 966 if (lun->state == CFI_LUN_READCAPACITY) { 967 struct scsi_read_capacity_data *rdcap; 968 969 rdcap = (struct scsi_read_capacity_data *) 970 io->scsiio.ext_data_ptr; 971 972 maxlba = scsi_4btoul(rdcap->addr); 973 blocksize = scsi_4btoul(rdcap->length); 974 if (blocksize == 0) { 975 printf("%s: LUN %d has invalid " 976 "blocksize 0, probe aborted\n", 977 __func__, lun->lun_id); 978 } else if (maxlba == 0xffffffff) { 979 lun->state = CFI_LUN_READCAPACITY_16; 980 cfi_lun_probe(lun, /*have_lock*/ 0); 981 } else 982 lun->state = CFI_LUN_READY; 983 } else { 984 struct scsi_read_capacity_data_long *rdcap_long; 985 986 rdcap_long = (struct 987 scsi_read_capacity_data_long *) 988 io->scsiio.ext_data_ptr; 989 maxlba = scsi_8btou64(rdcap_long->addr); 990 blocksize = scsi_4btoul(rdcap_long->length); 991 992 if (blocksize == 0) { 993 printf("%s: LUN %d has invalid " 994 "blocksize 0, probe aborted\n", 995 __func__, lun->lun_id); 996 } else 997 lun->state = CFI_LUN_READY; 998 } 999 } 1000 1001 if (lun->state == CFI_LUN_READY) { 1002 char path_str[40]; 1003 1004 lun->num_blocks = maxlba + 1; 1005 lun->blocksize = blocksize; 1006 1007 /* 1008 * If this is true, the blocksize is a power of 2. 1009 * We already checked for 0 above. 1010 */ 1011 if (((blocksize - 1) & blocksize) == 0) { 1012 int i; 1013 1014 for (i = 0; i < 32; i++) { 1015 if ((blocksize & (1 << i)) != 0) { 1016 lun->blocksize_powerof2 = i; 1017 break; 1018 } 1019 } 1020 } 1021 ctl_scsi_path_string(io, path_str,sizeof(path_str)); 1022 printf("%s", path_str); 1023 scsi_print_inquiry(&lun->inq_data); 1024 printf("%s %ju blocks, blocksize %d\n", path_str, 1025 (uintmax_t)maxlba + 1, blocksize); 1026 } 1027 mtx_lock(&lun->softc->lock); 1028 STAILQ_REMOVE(&lun->io_list, lun_io, cfi_lun_io, links); 1029 mtx_unlock(&lun->softc->lock); 1030 free(io->scsiio.ext_data_ptr, M_CTL_CFI); 1031 ctl_free_io(io); 1032 break; 1033 } 1034 case CFI_LUN_READY: 1035 default: 1036 mtx_lock(&lun->softc->lock); 1037 /* How did we get here?? */ 1038 STAILQ_REMOVE(&lun->io_list, lun_io, cfi_lun_io, links); 1039 mtx_unlock(&lun->softc->lock); 1040 ctl_free_io(io); 1041 break; 1042 } 1043} 1044 1045static void 1046cfi_lun_probe(struct cfi_lun *lun, int have_lock) 1047{ 1048 1049 if (have_lock == 0) 1050 mtx_lock(&lun->softc->lock); 1051 if ((lun->softc->flags & CFI_ONLINE) == 0) { 1052 if (have_lock == 0) 1053 mtx_unlock(&lun->softc->lock); 1054 return; 1055 } 1056 if (have_lock == 0) 1057 mtx_unlock(&lun->softc->lock); 1058 1059 switch (lun->state) { 1060 case CFI_LUN_INQUIRY: { 1061 struct cfi_lun_io *lun_io; 1062 union ctl_io *io; 1063 1064 io = ctl_alloc_io(lun->softc->fe.ctl_pool_ref); 1065 if (io == NULL) { 1066 printf("%s: unable to alloc ctl_io for target %ju " 1067 "lun %d probe\n", __func__, 1068 (uintmax_t)lun->target_id.id, lun->lun_id); 1069 return; 1070 } 1071 ctl_scsi_inquiry(io, 1072 /*data_ptr*/(uint8_t *)&lun->inq_data, 1073 /*data_len*/ sizeof(lun->inq_data), 1074 /*byte2*/ 0, 1075 /*page_code*/ 0, 1076 /*tag_type*/ CTL_TAG_SIMPLE, 1077 /*control*/ 0); 1078 1079 cfi_init_io(io, 1080 /*lun*/ lun, 1081 /*metatask*/ NULL, 1082 /*policy*/ CFI_ERR_SOFT, 1083 /*retries*/ 5, 1084 /*orig_lun_io*/ NULL, 1085 /*done_function*/ 1086 cfi_lun_probe_done); 1087 1088 lun_io = (struct cfi_lun_io *)io->io_hdr.port_priv; 1089 1090 if (have_lock == 0) 1091 mtx_lock(&lun->softc->lock); 1092 STAILQ_INSERT_TAIL(&lun->io_list, lun_io, links); 1093 if (have_lock == 0) 1094 mtx_unlock(&lun->softc->lock); 1095 1096 if (ctl_queue(io) != CTL_RETVAL_COMPLETE) { 1097 printf("%s: error returned from ctl_queue()!\n", 1098 __func__); 1099 STAILQ_REMOVE(&lun->io_list, lun_io, 1100 cfi_lun_io, links); 1101 ctl_free_io(io); 1102 } 1103 break; 1104 } 1105 case CFI_LUN_READCAPACITY: 1106 case CFI_LUN_READCAPACITY_16: { 1107 struct cfi_lun_io *lun_io; 1108 uint8_t *dataptr; 1109 union ctl_io *io; 1110 1111 io = ctl_alloc_io(lun->softc->fe.ctl_pool_ref); 1112 if (io == NULL) { 1113 printf("%s: unable to alloc ctl_io for target %ju " 1114 "lun %d probe\n", __func__, 1115 (uintmax_t)lun->target_id.id, lun->lun_id); 1116 return; 1117 } 1118 1119 dataptr = malloc(sizeof(struct scsi_read_capacity_data_long), 1120 M_CTL_CFI, M_NOWAIT); 1121 if (dataptr == NULL) { 1122 printf("%s: unable to allocate SCSI read capacity " 1123 "buffer for target %ju lun %d\n", __func__, 1124 (uintmax_t)lun->target_id.id, lun->lun_id); 1125 return; 1126 } 1127 if (lun->state == CFI_LUN_READCAPACITY) { 1128 ctl_scsi_read_capacity(io, 1129 /*data_ptr*/ dataptr, 1130 /*data_len*/ 1131 sizeof(struct scsi_read_capacity_data_long), 1132 /*addr*/ 0, 1133 /*reladr*/ 0, 1134 /*pmi*/ 0, 1135 /*tag_type*/ CTL_TAG_SIMPLE, 1136 /*control*/ 0); 1137 } else { 1138 ctl_scsi_read_capacity_16(io, 1139 /*data_ptr*/ dataptr, 1140 /*data_len*/ 1141 sizeof(struct scsi_read_capacity_data_long), 1142 /*addr*/ 0, 1143 /*reladr*/ 0, 1144 /*pmi*/ 0, 1145 /*tag_type*/ CTL_TAG_SIMPLE, 1146 /*control*/ 0); 1147 } 1148 cfi_init_io(io, 1149 /*lun*/ lun, 1150 /*metatask*/ NULL, 1151 /*policy*/ CFI_ERR_SOFT, 1152 /*retries*/ 7, 1153 /*orig_lun_io*/ NULL, 1154 /*done_function*/ cfi_lun_probe_done); 1155 1156 lun_io = (struct cfi_lun_io *)io->io_hdr.port_priv; 1157 1158 if (have_lock == 0) 1159 mtx_lock(&lun->softc->lock); 1160 STAILQ_INSERT_TAIL(&lun->io_list, lun_io, links); 1161 if (have_lock == 0) 1162 mtx_unlock(&lun->softc->lock); 1163 1164 if (ctl_queue(io) != CTL_RETVAL_COMPLETE) { 1165 printf("%s: error returned from ctl_queue()!\n", 1166 __func__); 1167 STAILQ_REMOVE(&lun->io_list, lun_io, 1168 cfi_lun_io, links); 1169 free(dataptr, M_CTL_CFI); 1170 ctl_free_io(io); 1171 } 1172 break; 1173 } 1174 case CFI_LUN_READY: 1175 default: 1176 /* Why were we called? */ 1177 break; 1178 } 1179} 1180 1181static void 1182cfi_metatask_done(struct cfi_softc *softc, struct cfi_metatask *metatask) 1183{ 1184 mtx_lock(&softc->lock); 1185 STAILQ_REMOVE(&softc->metatask_list, metatask, cfi_metatask, links); 1186 mtx_unlock(&softc->lock); 1187 1188 /* 1189 * Return status to the caller. Caller allocated storage, and is 1190 * responsible for calling cfi_free_metatask to release it once 1191 * they've seen the status. 1192 */ 1193 metatask->callback(metatask->callback_arg, metatask); 1194} 1195 1196static void 1197cfi_metatask_bbr_errorparse(struct cfi_metatask *metatask, union ctl_io *io) 1198{ 1199 int error_code, sense_key, asc, ascq; 1200 1201 if (metatask->tasktype != CFI_TASK_BBRREAD) 1202 return; 1203 1204 if ((io->io_hdr.status & CTL_STATUS_MASK) == CTL_SUCCESS) { 1205 metatask->status = CFI_MT_SUCCESS; 1206 metatask->taskinfo.bbrread.status = CFI_BBR_SUCCESS; 1207 return; 1208 } 1209 1210 if ((io->io_hdr.status & CTL_STATUS_MASK) != CTL_SCSI_ERROR) { 1211 metatask->status = CFI_MT_ERROR; 1212 metatask->taskinfo.bbrread.status = CFI_BBR_ERROR; 1213 return; 1214 } 1215 1216 metatask->taskinfo.bbrread.scsi_status = io->scsiio.scsi_status; 1217 memcpy(&metatask->taskinfo.bbrread.sense_data, &io->scsiio.sense_data, 1218 ctl_min(sizeof(metatask->taskinfo.bbrread.sense_data), 1219 sizeof(io->scsiio.sense_data))); 1220 1221 if (io->scsiio.scsi_status == SCSI_STATUS_RESERV_CONFLICT) { 1222 metatask->status = CFI_MT_ERROR; 1223 metatask->taskinfo.bbrread.status = CFI_BBR_RESERV_CONFLICT; 1224 return; 1225 } 1226 1227 if (io->scsiio.scsi_status != SCSI_STATUS_CHECK_COND) { 1228 metatask->status = CFI_MT_ERROR; 1229 metatask->taskinfo.bbrread.status = CFI_BBR_SCSI_ERROR; 1230 return; 1231 } 1232 1233 scsi_extract_sense_len(&io->scsiio.sense_data, 1234 io->scsiio.sense_len, 1235 &error_code, 1236 &sense_key, 1237 &asc, 1238 &ascq, 1239 /*show_errors*/ 1); 1240 1241 switch (error_code) { 1242 case SSD_DEFERRED_ERROR: 1243 case SSD_DESC_DEFERRED_ERROR: 1244 metatask->status = CFI_MT_ERROR; 1245 metatask->taskinfo.bbrread.status = CFI_BBR_SCSI_ERROR; 1246 break; 1247 case SSD_CURRENT_ERROR: 1248 case SSD_DESC_CURRENT_ERROR: 1249 default: { 1250 struct scsi_sense_data *sense; 1251 1252 sense = &io->scsiio.sense_data; 1253 1254 if ((asc == 0x04) && (ascq == 0x02)) { 1255 metatask->status = CFI_MT_ERROR; 1256 metatask->taskinfo.bbrread.status = CFI_BBR_LUN_STOPPED; 1257 } else if ((asc == 0x04) && (ascq == 0x03)) { 1258 metatask->status = CFI_MT_ERROR; 1259 metatask->taskinfo.bbrread.status = 1260 CFI_BBR_LUN_OFFLINE_CTL; 1261 } else if ((asc == 0x44) && (ascq == 0x00)) { 1262#ifdef NEEDTOPORT 1263 if (sense->sense_key_spec[0] & SSD_SCS_VALID) { 1264 uint16_t retry_count; 1265 1266 retry_count = sense->sense_key_spec[1] << 8 | 1267 sense->sense_key_spec[2]; 1268 if (((retry_count & 0xf000) == CSC_RAIDCORE) 1269 && ((retry_count & 0x0f00) == CSC_SHELF_SW) 1270 && ((retry_count & 0xff) == 1271 RC_STS_DEVICE_OFFLINE)) { 1272 metatask->status = CFI_MT_ERROR; 1273 metatask->taskinfo.bbrread.status = 1274 CFI_BBR_LUN_OFFLINE_RC; 1275 } else { 1276 metatask->status = CFI_MT_ERROR; 1277 metatask->taskinfo.bbrread.status = 1278 CFI_BBR_SCSI_ERROR; 1279 } 1280 } else { 1281#endif /* NEEDTOPORT */ 1282 metatask->status = CFI_MT_ERROR; 1283 metatask->taskinfo.bbrread.status = 1284 CFI_BBR_SCSI_ERROR; 1285#ifdef NEEDTOPORT 1286 } 1287#endif 1288 } else { 1289 metatask->status = CFI_MT_ERROR; 1290 metatask->taskinfo.bbrread.status = CFI_BBR_SCSI_ERROR; 1291 } 1292 break; 1293 } 1294 } 1295} 1296 1297static void 1298cfi_metatask_io_done(union ctl_io *io) 1299{ 1300 struct cfi_lun_io *lun_io; 1301 struct cfi_metatask *metatask; 1302 struct cfi_softc *softc; 1303 struct cfi_lun *lun; 1304 1305 lun_io = (struct cfi_lun_io *) 1306 io->io_hdr.ctl_private[CTL_PRIV_FRONTEND].ptr; 1307 1308 lun = lun_io->lun; 1309 softc = lun->softc; 1310 1311 metatask = lun_io->metatask; 1312 1313 switch (metatask->tasktype) { 1314 case CFI_TASK_STARTUP: 1315 case CFI_TASK_SHUTDOWN: { 1316 int failed, done, is_start; 1317 1318 failed = 0; 1319 done = 0; 1320 if (metatask->tasktype == CFI_TASK_STARTUP) 1321 is_start = 1; 1322 else 1323 is_start = 0; 1324 1325 mtx_lock(&softc->lock); 1326 if ((io->io_hdr.status & CTL_STATUS_MASK) == CTL_SUCCESS) 1327 metatask->taskinfo.startstop.luns_complete++; 1328 else { 1329 metatask->taskinfo.startstop.luns_failed++; 1330 failed = 1; 1331 } 1332 if ((metatask->taskinfo.startstop.luns_complete + 1333 metatask->taskinfo.startstop.luns_failed) >= 1334 metatask->taskinfo.startstop.total_luns) 1335 done = 1; 1336 1337 mtx_unlock(&softc->lock); 1338 1339 if (failed != 0) { 1340 printf("%s: LUN %d %s request failed\n", __func__, 1341 lun_io->lun->lun_id, (is_start == 1) ? "start" : 1342 "stop"); 1343 ctl_io_error_print(io, &lun_io->lun->inq_data); 1344 } 1345 if (done != 0) { 1346 if (metatask->taskinfo.startstop.luns_failed > 0) 1347 metatask->status = CFI_MT_ERROR; 1348 else 1349 metatask->status = CFI_MT_SUCCESS; 1350 cfi_metatask_done(softc, metatask); 1351 } 1352 mtx_lock(&softc->lock); 1353 STAILQ_REMOVE(&lun->io_list, lun_io, cfi_lun_io, links); 1354 mtx_unlock(&softc->lock); 1355 1356 ctl_free_io(io); 1357 break; 1358 } 1359 case CFI_TASK_BBRREAD: { 1360 /* 1361 * Translate the SCSI error into an enumeration. 1362 */ 1363 cfi_metatask_bbr_errorparse(metatask, io); 1364 1365 mtx_lock(&softc->lock); 1366 STAILQ_REMOVE(&lun->io_list, lun_io, cfi_lun_io, links); 1367 mtx_unlock(&softc->lock); 1368 1369 ctl_free_io(io); 1370 1371 cfi_metatask_done(softc, metatask); 1372 break; 1373 } 1374 default: 1375 /* 1376 * This shouldn't happen. 1377 */ 1378 mtx_lock(&softc->lock); 1379 STAILQ_REMOVE(&lun->io_list, lun_io, cfi_lun_io, links); 1380 mtx_unlock(&softc->lock); 1381 1382 ctl_free_io(io); 1383 break; 1384 } 1385} 1386 1387static void 1388cfi_err_recovery_done(union ctl_io *io) 1389{ 1390 struct cfi_lun_io *lun_io, *orig_lun_io; 1391 struct cfi_lun *lun; 1392 union ctl_io *orig_io; 1393 1394 lun_io = (struct cfi_lun_io *)io->io_hdr.port_priv; 1395 orig_lun_io = lun_io->orig_lun_io; 1396 orig_io = orig_lun_io->ctl_io; 1397 lun = lun_io->lun; 1398 1399 if (io->io_hdr.status != CTL_SUCCESS) { 1400 printf("%s: error recovery action failed. Original " 1401 "error:\n", __func__); 1402 1403 ctl_io_error_print(orig_lun_io->ctl_io, &lun->inq_data); 1404 1405 printf("%s: error from error recovery action:\n", __func__); 1406 1407 ctl_io_error_print(io, &lun->inq_data); 1408 1409 printf("%s: trying original command again...\n", __func__); 1410 } 1411 1412 mtx_lock(&lun->softc->lock); 1413 STAILQ_REMOVE(&lun->io_list, lun_io, cfi_lun_io, links); 1414 mtx_unlock(&lun->softc->lock); 1415 ctl_free_io(io); 1416 1417 orig_io->io_hdr.retries--; 1418 orig_io->io_hdr.status = CTL_STATUS_NONE; 1419 1420 if (ctl_queue(orig_io) != CTL_RETVAL_COMPLETE) { 1421 printf("%s: error returned from ctl_queue()!\n", __func__); 1422 STAILQ_REMOVE(&lun->io_list, orig_lun_io, 1423 cfi_lun_io, links); 1424 ctl_free_io(orig_io); 1425 } 1426} 1427 1428static void 1429cfi_lun_io_done(union ctl_io *io) 1430{ 1431 struct cfi_lun *lun; 1432 struct cfi_lun_io *lun_io; 1433 1434 lun_io = (struct cfi_lun_io *) 1435 io->io_hdr.ctl_private[CTL_PRIV_FRONTEND].ptr; 1436 lun = lun_io->lun; 1437 1438 if (lun_io->metatask == NULL) { 1439 printf("%s: I/O has no metatask pointer, discarding\n", 1440 __func__); 1441 STAILQ_REMOVE(&lun->io_list, lun_io, cfi_lun_io, links); 1442 ctl_free_io(io); 1443 return; 1444 } 1445 cfi_metatask_io_done(io); 1446} 1447 1448void 1449cfi_action(struct cfi_metatask *metatask) 1450{ 1451 struct cfi_softc *softc; 1452 1453 softc = &fetd_internal_softc; 1454 1455 mtx_lock(&softc->lock); 1456 1457 STAILQ_INSERT_TAIL(&softc->metatask_list, metatask, links); 1458 1459 if ((softc->flags & CFI_ONLINE) == 0) { 1460 mtx_unlock(&softc->lock); 1461 metatask->status = CFI_MT_PORT_OFFLINE; 1462 cfi_metatask_done(softc, metatask); 1463 return; 1464 } else 1465 mtx_unlock(&softc->lock); 1466 1467 switch (metatask->tasktype) { 1468 case CFI_TASK_STARTUP: 1469 case CFI_TASK_SHUTDOWN: { 1470 union ctl_io *io; 1471 int da_luns, ios_allocated, do_start; 1472 struct cfi_lun *lun; 1473 STAILQ_HEAD(, ctl_io_hdr) tmp_io_list; 1474 1475 da_luns = 0; 1476 ios_allocated = 0; 1477 STAILQ_INIT(&tmp_io_list); 1478 1479 if (metatask->tasktype == CFI_TASK_STARTUP) 1480 do_start = 1; 1481 else 1482 do_start = 0; 1483 1484 mtx_lock(&softc->lock); 1485 STAILQ_FOREACH(lun, &softc->lun_list, links) { 1486 if (lun->state != CFI_LUN_READY) 1487 continue; 1488 1489 if (SID_TYPE(&lun->inq_data) != T_DIRECT) 1490 continue; 1491 da_luns++; 1492 io = ctl_alloc_io(softc->fe.ctl_pool_ref); 1493 if (io != NULL) { 1494 ios_allocated++; 1495 STAILQ_INSERT_TAIL(&tmp_io_list, &io->io_hdr, 1496 links); 1497 } 1498 } 1499 1500 if (ios_allocated < da_luns) { 1501 printf("%s: error allocating ctl_io for %s\n", 1502 __func__, (do_start == 1) ? "startup" : 1503 "shutdown"); 1504 da_luns = ios_allocated; 1505 } 1506 1507 metatask->taskinfo.startstop.total_luns = da_luns; 1508 1509 STAILQ_FOREACH(lun, &softc->lun_list, links) { 1510 struct cfi_lun_io *lun_io; 1511 1512 if (lun->state != CFI_LUN_READY) 1513 continue; 1514 1515 if (SID_TYPE(&lun->inq_data) != T_DIRECT) 1516 continue; 1517 1518 io = (union ctl_io *)STAILQ_FIRST(&tmp_io_list); 1519 if (io == NULL) 1520 break; 1521 1522 STAILQ_REMOVE(&tmp_io_list, &io->io_hdr, ctl_io_hdr, 1523 links); 1524 1525 ctl_scsi_start_stop(io, 1526 /*start*/ do_start, 1527 /*load_eject*/ 0, 1528 /*immediate*/ 0, 1529 /*power_conditions*/ 1530 SSS_PC_START_VALID, 1531 /*onoffline*/ 1, 1532 /*ctl_tag_type*/ CTL_TAG_ORDERED, 1533 /*control*/ 0); 1534 1535 cfi_init_io(io, 1536 /*lun*/ lun, 1537 /*metatask*/ metatask, 1538 /*policy*/ CFI_ERR_HARD, 1539 /*retries*/ 3, 1540 /*orig_lun_io*/ NULL, 1541 /*done_function*/ cfi_lun_io_done); 1542 1543 lun_io = (struct cfi_lun_io *) io->io_hdr.port_priv; 1544 1545 STAILQ_INSERT_TAIL(&lun->io_list, lun_io, links); 1546 1547 if (ctl_queue(io) != CTL_RETVAL_COMPLETE) { 1548 printf("%s: error returned from ctl_queue()!\n", 1549 __func__); 1550 STAILQ_REMOVE(&lun->io_list, lun_io, 1551 cfi_lun_io, links); 1552 ctl_free_io(io); 1553 metatask->taskinfo.startstop.total_luns--; 1554 } 1555 } 1556 1557 if (STAILQ_FIRST(&tmp_io_list) != NULL) { 1558 printf("%s: error: tmp_io_list != NULL\n", __func__); 1559 for (io = (union ctl_io *)STAILQ_FIRST(&tmp_io_list); 1560 io != NULL; 1561 io = (union ctl_io *)STAILQ_FIRST(&tmp_io_list)) { 1562 STAILQ_REMOVE(&tmp_io_list, &io->io_hdr, 1563 ctl_io_hdr, links); 1564 ctl_free_io(io); 1565 } 1566 } 1567 mtx_unlock(&softc->lock); 1568 1569 break; 1570 } 1571 case CFI_TASK_BBRREAD: { 1572 union ctl_io *io; 1573 struct cfi_lun *lun; 1574 struct cfi_lun_io *lun_io; 1575 cfi_bbrread_status status; 1576 int req_lun_num; 1577 uint32_t num_blocks; 1578 1579 status = CFI_BBR_SUCCESS; 1580 1581 req_lun_num = metatask->taskinfo.bbrread.lun_num; 1582 1583 mtx_lock(&softc->lock); 1584 STAILQ_FOREACH(lun, &softc->lun_list, links) { 1585 if (lun->lun_id != req_lun_num) 1586 continue; 1587 if (lun->state != CFI_LUN_READY) { 1588 status = CFI_BBR_LUN_UNCONFIG; 1589 break; 1590 } else 1591 break; 1592 } 1593 1594 if (lun == NULL) 1595 status = CFI_BBR_NO_LUN; 1596 1597 if (status != CFI_BBR_SUCCESS) { 1598 metatask->status = CFI_MT_ERROR; 1599 metatask->taskinfo.bbrread.status = status; 1600 mtx_unlock(&softc->lock); 1601 cfi_metatask_done(softc, metatask); 1602 break; 1603 } 1604 1605 /* 1606 * Convert the number of bytes given into blocks and check 1607 * that the number of bytes is a multiple of the blocksize. 1608 * CTL will verify that the LBA is okay. 1609 */ 1610 if (lun->blocksize_powerof2 != 0) { 1611 if ((metatask->taskinfo.bbrread.len & 1612 (lun->blocksize - 1)) != 0) { 1613 metatask->status = CFI_MT_ERROR; 1614 metatask->taskinfo.bbrread.status = 1615 CFI_BBR_BAD_LEN; 1616 cfi_metatask_done(softc, metatask); 1617 break; 1618 } 1619 1620 num_blocks = metatask->taskinfo.bbrread.len >> 1621 lun->blocksize_powerof2; 1622 } else { 1623 /* 1624 * XXX KDM this could result in floating point 1625 * division, which isn't supported in the kernel on 1626 * x86 at least. 1627 */ 1628 if ((metatask->taskinfo.bbrread.len % 1629 lun->blocksize) != 0) { 1630 metatask->status = CFI_MT_ERROR; 1631 metatask->taskinfo.bbrread.status = 1632 CFI_BBR_BAD_LEN; 1633 cfi_metatask_done(softc, metatask); 1634 break; 1635 } 1636 1637 /* 1638 * XXX KDM this could result in floating point 1639 * division in some cases. 1640 */ 1641 num_blocks = metatask->taskinfo.bbrread.len / 1642 lun->blocksize; 1643 1644 } 1645 1646 io = ctl_alloc_io(softc->fe.ctl_pool_ref); 1647 if (io == NULL) { 1648 metatask->status = CFI_MT_ERROR; 1649 metatask->taskinfo.bbrread.status = CFI_BBR_NO_MEM; 1650 mtx_unlock(&softc->lock); 1651 cfi_metatask_done(softc, metatask); 1652 break; 1653 } 1654 1655 /* 1656 * XXX KDM need to do a read capacity to get the blocksize 1657 * for this device. 1658 */ 1659 ctl_scsi_read_write(io, 1660 /*data_ptr*/ NULL, 1661 /*data_len*/ metatask->taskinfo.bbrread.len, 1662 /*read_op*/ 1, 1663 /*byte2*/ 0, 1664 /*minimum_cdb_size*/ 0, 1665 /*lba*/ metatask->taskinfo.bbrread.lba, 1666 /*num_blocks*/ num_blocks, 1667 /*tag_type*/ CTL_TAG_SIMPLE, 1668 /*control*/ 0); 1669 1670 cfi_init_io(io, 1671 /*lun*/ lun, 1672 /*metatask*/ metatask, 1673 /*policy*/ CFI_ERR_SOFT, 1674 /*retries*/ 3, 1675 /*orig_lun_io*/ NULL, 1676 /*done_function*/ cfi_lun_io_done); 1677 1678 lun_io = (struct cfi_lun_io *)io->io_hdr.port_priv; 1679 1680 STAILQ_INSERT_TAIL(&lun->io_list, lun_io, links); 1681 1682 if (ctl_queue(io) != CTL_RETVAL_COMPLETE) { 1683 printf("%s: error returned from ctl_queue()!\n", 1684 __func__); 1685 STAILQ_REMOVE(&lun->io_list, lun_io, cfi_lun_io, links); 1686 ctl_free_io(io); 1687 metatask->status = CFI_MT_ERROR; 1688 metatask->taskinfo.bbrread.status = CFI_BBR_ERROR; 1689 mtx_unlock(&softc->lock); 1690 cfi_metatask_done(softc, metatask); 1691 break; 1692 } 1693 1694 mtx_unlock(&softc->lock); 1695 break; 1696 } 1697 default: 1698 panic("invalid metatask type %d", metatask->tasktype); 1699 break; /* NOTREACHED */ 1700 } 1701} 1702 1703#ifdef oldapi 1704void 1705cfi_shutdown_shelf(cfi_cb_t callback, void *callback_arg) 1706{ 1707 struct ctl_mem_element *element; 1708 struct cfi_softc *softc; 1709 struct cfi_metatask *metatask; 1710 1711 softc = &fetd_internal_softc; 1712 1713 element = ctl_alloc_mem_element(&softc->metatask_pool, /*can_wait*/ 0); 1714 if (element == NULL) { 1715 callback(callback_arg, 1716 /*status*/ CFI_MT_ERROR, 1717 /*sluns_found*/ 0, 1718 /*sluns_complete*/ 0, 1719 /*sluns_failed*/ 0); 1720 return; 1721 } 1722 1723 metatask = (struct cfi_metatask *)element->bytes; 1724 1725 memset(metatask, 0, sizeof(*metatask)); 1726 metatask->tasktype = CFI_TASK_SHUTDOWN; 1727 metatask->status = CFI_MT_NONE; 1728 metatask->taskinfo.startstop.callback = callback; 1729 metatask->taskinfo.startstop.callback_arg = callback_arg; 1730 metatask->element = element; 1731 1732 cfi_action(softc, metatask); 1733 1734 /* 1735 * - send a report luns to lun 0, get LUN list. 1736 * - send an inquiry to each lun 1737 * - send a stop/offline to each direct access LUN 1738 * - if we get a reservation conflict, reset the LUN and then 1739 * retry sending the stop/offline 1740 * - return status back to the caller 1741 */ 1742} 1743 1744void 1745cfi_start_shelf(cfi_cb_t callback, void *callback_arg) 1746{ 1747 struct ctl_mem_element *element; 1748 struct cfi_softc *softc; 1749 struct cfi_metatask *metatask; 1750 1751 softc = &fetd_internal_softc; 1752 1753 element = ctl_alloc_mem_element(&softc->metatask_pool, /*can_wait*/ 0); 1754 if (element == NULL) { 1755 callback(callback_arg, 1756 /*status*/ CFI_MT_ERROR, 1757 /*sluns_found*/ 0, 1758 /*sluns_complete*/ 0, 1759 /*sluns_failed*/ 0); 1760 return; 1761 } 1762 1763 metatask = (struct cfi_metatask *)element->bytes; 1764 1765 memset(metatask, 0, sizeof(*metatask)); 1766 metatask->tasktype = CFI_TASK_STARTUP; 1767 metatask->status = CFI_MT_NONE; 1768 metatask->taskinfo.startstop.callback = callback; 1769 metatask->taskinfo.startstop.callback_arg = callback_arg; 1770 metatask->element = element; 1771 1772 cfi_action(softc, metatask); 1773 1774 /* 1775 * - send a report luns to lun 0, get LUN list. 1776 * - send an inquiry to each lun 1777 * - send a stop/offline to each direct access LUN 1778 * - if we get a reservation conflict, reset the LUN and then 1779 * retry sending the stop/offline 1780 * - return status back to the caller 1781 */ 1782} 1783 1784#endif 1785 1786struct cfi_metatask * 1787cfi_alloc_metatask(int can_wait) 1788{ 1789 struct ctl_mem_element *element; 1790 struct cfi_metatask *metatask; 1791 struct cfi_softc *softc; 1792 1793 softc = &fetd_internal_softc; 1794 1795 element = ctl_alloc_mem_element(&softc->metatask_pool, can_wait); 1796 if (element == NULL) 1797 return (NULL); 1798 1799 metatask = (struct cfi_metatask *)element->bytes; 1800 memset(metatask, 0, sizeof(*metatask)); 1801 metatask->status = CFI_MT_NONE; 1802 metatask->element = element; 1803 1804 return (metatask); 1805} 1806 1807void 1808cfi_free_metatask(struct cfi_metatask *metatask) 1809{ 1810 ctl_free_mem_element(metatask->element); 1811} 1812 1813/* 1814 * vim: ts=8 1815 */ 1816