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