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