xref: /trueos/sys/cam/ctl/ctl_frontend_internal.c (revision 0767d4eb72eeb6b085335acd9b79092f1e69e76e)
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