Deleted Added
sdiff udiff text old ( 237601 ) new ( 237726 )
full compact
1/*-
2 * Copyright (c) 2008, 2009 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/scsi_ctl.c#4 $
31 */
32/*
33 * Peripheral driver interface between CAM and CTL (CAM Target Layer).
34 *
35 * Author: Ken Merry <ken@FreeBSD.org>
36 */
37
38#include <sys/cdefs.h>
39__FBSDID("$FreeBSD: head/sys/cam/ctl/scsi_ctl.c 237601 2012-06-26 14:51:35Z ken $");
40
41#include <sys/param.h>
42#include <sys/queue.h>
43#include <sys/systm.h>
44#include <sys/kernel.h>
45#include <sys/lock.h>
46#include <sys/mutex.h>
47#include <sys/condvar.h>
48#include <sys/malloc.h>
49#include <sys/bus.h>
50#include <sys/endian.h>
51#include <sys/sbuf.h>
52#include <sys/sysctl.h>
53#include <sys/types.h>
54#include <sys/systm.h>
55#include <machine/bus.h>
56
57#include <cam/cam.h>
58#include <cam/cam_ccb.h>
59#include <cam/cam_periph.h>
60#include <cam/cam_queue.h>
61#include <cam/cam_xpt_periph.h>
62#include <cam/cam_debug.h>
63#include <cam/cam_sim.h>
64#include <cam/cam_xpt.h>
65
66#include <cam/scsi/scsi_all.h>
67#include <cam/scsi/scsi_message.h>
68
69#include <cam/ctl/ctl_io.h>
70#include <cam/ctl/ctl.h>
71#include <cam/ctl/ctl_frontend.h>
72#include <cam/ctl/ctl_util.h>
73#include <cam/ctl/ctl_error.h>
74
75typedef enum {
76 CTLFE_CCB_WAITING = 0x01
77} ctlfe_ccb_types;
78
79struct ctlfe_softc {
80 struct ctl_frontend fe;
81 path_id_t path_id;
82 struct cam_sim *sim;
83 char port_name[DEV_IDLEN];
84 STAILQ_HEAD(, ctlfe_lun_softc) lun_softc_list;
85 STAILQ_ENTRY(ctlfe_softc) links;
86};
87
88STAILQ_HEAD(, ctlfe_softc) ctlfe_softc_list;
89struct mtx ctlfe_list_mtx;
90static char ctlfe_mtx_desc[] = "ctlfelist";
91static int ctlfe_dma_enabled = 1;
92#ifdef CTLFE_INIT_ENABLE
93static int ctlfe_max_targets = 1;
94static int ctlfe_num_targets = 0;
95#endif
96
97typedef enum {
98 CTLFE_LUN_NONE = 0x00,
99 CTLFE_LUN_WILDCARD = 0x01
100} ctlfe_lun_flags;
101
102struct ctlfe_lun_softc {
103 struct ctlfe_softc *parent_softc;
104 struct cam_periph *periph;
105 ctlfe_lun_flags flags;
106 struct callout dma_callout;
107 uint64_t ccbs_alloced;
108 uint64_t ccbs_freed;
109 uint64_t ctios_sent;
110 uint64_t ctios_returned;
111 uint64_t atios_sent;
112 uint64_t atios_returned;
113 uint64_t inots_sent;
114 uint64_t inots_returned;
115 /* bus_dma_tag_t dma_tag; */
116 TAILQ_HEAD(, ccb_hdr) work_queue;
117 STAILQ_ENTRY(ctlfe_lun_softc) links;
118};
119
120typedef enum {
121 CTLFE_CMD_NONE = 0x00,
122 CTLFE_CMD_PIECEWISE = 0x01
123} ctlfe_cmd_flags;
124
125/*
126 * The size limit of this structure is CTL_PORT_PRIV_SIZE, from ctl_io.h.
127 * Currently that is 600 bytes.
128 */
129struct ctlfe_lun_cmd_info {
130 int cur_transfer_index;
131 ctlfe_cmd_flags flags;
132 /*
133 * XXX KDM struct bus_dma_segment is 8 bytes on i386, and 16
134 * bytes on amd64. So with 32 elements, this is 256 bytes on
135 * i386 and 512 bytes on amd64.
136 */
137 bus_dma_segment_t cam_sglist[32];
138};
139
140/*
141 * When we register the adapter/bus, request that this many ctl_ios be
142 * allocated. This should be the maximum supported by the adapter, but we
143 * currently don't have a way to get that back from the path inquiry.
144 * XXX KDM add that to the path inquiry.
145 */
146#define CTLFE_REQ_CTL_IO 4096
147/*
148 * Number of Accept Target I/O CCBs to allocate and queue down to the
149 * adapter per LUN.
150 * XXX KDM should this be controlled by CTL?
151 */
152#define CTLFE_ATIO_PER_LUN 1024
153/*
154 * Number of Immediate Notify CCBs (used for aborts, resets, etc.) to
155 * allocate and queue down to the adapter per LUN.
156 * XXX KDM should this be controlled by CTL?
157 */
158#define CTLFE_IN_PER_LUN 1024
159
160/*
161 * Timeout (in seconds) on CTIO CCB allocation for doing a DMA or sending
162 * status to the initiator. The SIM is expected to have its own timeouts,
163 * so we're not putting this timeout around the CCB execution time. The
164 * SIM should timeout and let us know if it has an issue.
165 */
166#define CTLFE_DMA_TIMEOUT 60
167
168/*
169 * Turn this on to enable extra debugging prints.
170 */
171#if 0
172#define CTLFE_DEBUG
173#endif
174
175/*
176 * Use randomly assigned WWNN/WWPN values. This is to work around an issue
177 * in the FreeBSD initiator that makes it unable to rescan the target if
178 * the target gets rebooted and the WWNN/WWPN stay the same.
179 */
180#if 0
181#define RANDOM_WWNN
182#endif
183
184SYSCTL_INT(_kern_cam_ctl, OID_AUTO, dma_enabled, CTLFLAG_RW,
185 &ctlfe_dma_enabled, 0, "DMA enabled");
186MALLOC_DEFINE(M_CTLFE, "CAM CTL FE", "CAM CTL FE interface");
187
188#define ccb_type ppriv_field0
189/* This is only used in the ATIO */
190#define io_ptr ppriv_ptr1
191
192/* This is only used in the CTIO */
193#define ccb_atio ppriv_ptr1
194
195int ctlfeinitialize(void);
196void ctlfeshutdown(void);
197static periph_init_t ctlfeinit;
198static void ctlfeasync(void *callback_arg, uint32_t code,
199 struct cam_path *path, void *arg);
200static periph_ctor_t ctlferegister;
201static periph_oninv_t ctlfeoninvalidate;
202static periph_dtor_t ctlfecleanup;
203static periph_start_t ctlfestart;
204static void ctlfedone(struct cam_periph *periph,
205 union ccb *done_ccb);
206
207static void ctlfe_onoffline(void *arg, int online);
208static void ctlfe_online(void *arg);
209static void ctlfe_offline(void *arg);
210static int ctlfe_targ_enable(void *arg, struct ctl_id targ_id);
211static int ctlfe_targ_disable(void *arg, struct ctl_id targ_id);
212static int ctlfe_lun_enable(void *arg, struct ctl_id targ_id,
213 int lun_id);
214static int ctlfe_lun_disable(void *arg, struct ctl_id targ_id,
215 int lun_id);
216static void ctlfe_dump_sim(struct cam_sim *sim);
217static void ctlfe_dump_queue(struct ctlfe_lun_softc *softc);
218static void ctlfe_dma_timeout(void *arg);
219static void ctlfe_datamove_done(union ctl_io *io);
220static void ctlfe_dump(void);
221
222static struct periph_driver ctlfe_driver =
223{
224 ctlfeinit, "ctl",
225 TAILQ_HEAD_INITIALIZER(ctlfe_driver.units), /*generation*/ 0
226};
227PERIPHDRIVER_DECLARE(ctl, ctlfe_driver);
228
229extern struct ctl_softc *control_softc;
230
231int
232ctlfeinitialize(void)
233{
234 cam_status status;
235
236 STAILQ_INIT(&ctlfe_softc_list);
237
238 mtx_init(&ctlfe_list_mtx, ctlfe_mtx_desc, NULL, MTX_DEF);
239
240 xpt_lock_buses();
241 periphdriver_register(&ctlfe_driver);
242 xpt_unlock_buses();
243
244 status = xpt_register_async(AC_PATH_REGISTERED | AC_PATH_DEREGISTERED |
245 AC_CONTRACT, ctlfeasync, NULL, NULL);
246
247 if (status != CAM_REQ_CMP) {
248 printf("ctl: Failed to attach async callback due to CAM "
249 "status 0x%x!\n", status);
250 }
251
252 return (0);
253}
254
255void
256ctlfeshutdown(void)
257{
258 return;
259}
260
261void
262ctlfeinit(void)
263{
264 cam_status status;
265
266 STAILQ_INIT(&ctlfe_softc_list);
267
268 mtx_init(&ctlfe_list_mtx, ctlfe_mtx_desc, NULL, MTX_DEF);
269
270 KASSERT(control_softc != NULL, ("CTL is not initialized!"));
271
272 status = xpt_register_async(AC_PATH_REGISTERED | AC_PATH_DEREGISTERED |
273 AC_CONTRACT, ctlfeasync, NULL, NULL);
274
275 if (status != CAM_REQ_CMP) {
276 printf("ctl: Failed to attach async callback due to CAM "
277 "status 0x%x!\n", status);
278 }
279}
280
281static void
282ctlfeasync(void *callback_arg, uint32_t code, struct cam_path *path, void *arg)
283{
284
285#ifdef CTLFEDEBUG
286 printf("%s: entered\n", __func__);
287#endif
288
289 /*
290 * When a new path gets registered, and it is capable of target
291 * mode, go ahead and attach. Later on, we may need to be more
292 * selective, but for now this will be sufficient.
293 */
294 switch (code) {
295 case AC_PATH_REGISTERED: {
296 struct ctl_frontend *fe;
297 struct ctlfe_softc *bus_softc;
298 struct ctlfe_lun_softc *lun_softc;
299 struct cam_path *path;
300 struct ccb_pathinq *cpi;
301 cam_status status;
302 int retval;
303
304 cpi = (struct ccb_pathinq *)arg;
305
306 /* Don't attach if it doesn't support target mode */
307 if ((cpi->target_sprt & PIT_PROCESSOR) == 0) {
308#ifdef CTLFEDEBUG
309 printf("%s: SIM %s%d doesn't support target mode\n",
310 __func__, cpi->dev_name, cpi->unit_number);
311#endif
312 break;
313 }
314
315#ifdef CTLFE_INIT_ENABLE
316 if (ctlfe_num_targets >= ctlfe_max_targets) {
317 union ccb *ccb;
318 struct cam_sim *sim;
319
320 ccb = (union ccb *)malloc(sizeof(*ccb), M_TEMP,
321 M_NOWAIT | M_ZERO);
322 if (ccb == NULL) {
323 printf("%s: unable to malloc CCB!\n", __func__);
324 xpt_free_path(path);
325 return;
326 }
327 xpt_setup_ccb(&ccb->ccb_h, cpi->ccb_h.path,
328 /*priority*/ 1);
329
330 sim = xpt_path_sim(cpi->ccb_h.path);
331
332 ccb->ccb_h.func_code = XPT_SET_SIM_KNOB;
333 ccb->knob.xport_specific.valid = KNOB_VALID_ROLE;
334 ccb->knob.xport_specific.fc.role = KNOB_ROLE_INITIATOR;
335
336 /* We should hold the SIM lock here */
337 mtx_assert(sim->mtx, MA_OWNED);
338
339 xpt_action(ccb);
340
341 if ((ccb->ccb_h.status & CAM_STATUS_MASK) !=
342 CAM_REQ_CMP) {
343 printf("%s: SIM %s%d (path id %d) initiator "
344 "enable failed with status %#x\n",
345 __func__, cpi->dev_name,
346 cpi->unit_number, cpi->ccb_h.path_id,
347 ccb->ccb_h.status);
348 } else {
349 printf("%s: SIM %s%d (path id %d) initiator "
350 "enable succeeded\n",
351 __func__, cpi->dev_name,
352 cpi->unit_number, cpi->ccb_h.path_id);
353 }
354
355 free(ccb, M_TEMP);
356
357 break;
358 } else {
359 ctlfe_num_targets++;
360 }
361
362 printf("%s: ctlfe_num_targets = %d\n", __func__,
363 ctlfe_num_targets);
364#endif /* CTLFE_INIT_ENABLE */
365
366 /*
367 * We're in an interrupt context here, so we have to
368 * use M_NOWAIT. Of course this means trouble if we
369 * can't allocate memory.
370 */
371 bus_softc = malloc(sizeof(*bus_softc), M_CTLFE,
372 M_NOWAIT | M_ZERO);
373 if (bus_softc == NULL) {
374 printf("%s: unable to malloc %zd bytes for softc\n",
375 __func__, sizeof(*bus_softc));
376 return;
377 }
378
379 bus_softc->path_id = cpi->ccb_h.path_id;
380 bus_softc->sim = xpt_path_sim(cpi->ccb_h.path);
381 STAILQ_INIT(&bus_softc->lun_softc_list);
382
383 fe = &bus_softc->fe;
384
385 /*
386 * XXX KDM should we be more accurate here ?
387 */
388 if (cpi->transport == XPORT_FC)
389 fe->port_type = CTL_PORT_FC;
390 else
391 fe->port_type = CTL_PORT_SCSI;
392
393 /* XXX KDM what should the real number be here? */
394 fe->num_requested_ctl_io = 4096;
395 snprintf(bus_softc->port_name, sizeof(bus_softc->port_name),
396 "%s%d", cpi->dev_name, cpi->unit_number);
397 /*
398 * XXX KDM it would be nice to allocate storage in the
399 * frontend structure itself.
400 */
401 fe->port_name = bus_softc->port_name;
402 fe->physical_port = cpi->unit_number;
403 fe->virtual_port = cpi->bus_id;
404 fe->port_online = ctlfe_online;
405 fe->port_offline = ctlfe_offline;
406 fe->onoff_arg = bus_softc;
407 fe->targ_enable = ctlfe_targ_enable;
408 fe->targ_disable = ctlfe_targ_disable;
409 fe->lun_enable = ctlfe_lun_enable;
410 fe->lun_disable = ctlfe_lun_disable;
411 fe->targ_lun_arg = bus_softc;
412 fe->fe_datamove = ctlfe_datamove_done;
413 fe->fe_done = ctlfe_datamove_done;
414 fe->fe_dump = ctlfe_dump;
415 /*
416 * XXX KDM the path inquiry doesn't give us the maximum
417 * number of targets supported.
418 */
419 fe->max_targets = cpi->max_target;
420 fe->max_target_id = cpi->max_target;
421
422 /*
423 * XXX KDM need to figure out whether we're the master or
424 * slave.
425 */
426#ifdef CTLFEDEBUG
427 printf("%s: calling ctl_frontend_register() for %s%d\n",
428 __func__, cpi->dev_name, cpi->unit_number);
429#endif
430 retval = ctl_frontend_register(fe, /*master_SC*/ 1);
431 if (retval != 0) {
432 printf("%s: ctl_frontend_register() failed with "
433 "error %d!\n", __func__, retval);
434 free(bus_softc, M_CTLFE);
435 break;
436 } else {
437 mtx_lock(&ctlfe_list_mtx);
438 STAILQ_INSERT_TAIL(&ctlfe_softc_list, bus_softc, links);
439 mtx_unlock(&ctlfe_list_mtx);
440 }
441
442 status = xpt_create_path(&path, /*periph*/ NULL,
443 bus_softc->path_id,CAM_TARGET_WILDCARD,
444 CAM_LUN_WILDCARD);
445 if (status != CAM_REQ_CMP) {
446 printf("%s: unable to create path for wildcard "
447 "periph\n", __func__);
448 break;
449 }
450 lun_softc = malloc(sizeof(*lun_softc), M_CTLFE,
451 M_NOWAIT | M_ZERO);
452 if (lun_softc == NULL) {
453 xpt_print(path, "%s: unable to allocate softc for "
454 "wildcard periph\n", __func__);
455 xpt_free_path(path);
456 break;
457 }
458
459 lun_softc->parent_softc = bus_softc;
460 lun_softc->flags |= CTLFE_LUN_WILDCARD;
461
462 status = cam_periph_alloc(ctlferegister,
463 ctlfeoninvalidate,
464 ctlfecleanup,
465 ctlfestart,
466 "ctl",
467 CAM_PERIPH_BIO,
468 path,
469 ctlfeasync,
470 0,
471 lun_softc);
472
473 xpt_free_path(path);
474
475 break;
476 }
477 case AC_PATH_DEREGISTERED:
478 /* ctl_frontend_deregister() */
479 break;
480 case AC_CONTRACT: {
481 struct ac_contract *ac;
482
483 ac = (struct ac_contract *)arg;
484
485 switch (ac->contract_number) {
486 case AC_CONTRACT_DEV_CHG: {
487 struct ac_device_changed *dev_chg;
488 struct ctlfe_softc *softc;
489 int retval, found;
490
491 dev_chg = (struct ac_device_changed *)ac->contract_data;
492
493 printf("%s: WWPN %#jx port 0x%06x path %u target %u %s\n",
494 __func__, dev_chg->wwpn, dev_chg->port,
495 xpt_path_path_id(path), dev_chg->target,
496 (dev_chg->arrived == 0) ? "left" : "arrived");
497
498 found = 0;
499
500 mtx_lock(&ctlfe_list_mtx);
501 STAILQ_FOREACH(softc, &ctlfe_softc_list, links) {
502 if (softc->path_id == xpt_path_path_id(path)) {
503 found = 1;
504 break;
505 }
506 }
507 mtx_unlock(&ctlfe_list_mtx);
508
509 if (found == 0) {
510 printf("%s: CTL port for CAM path %u not "
511 "found!\n", __func__,
512 xpt_path_path_id(path));
513 break;
514 }
515 if (dev_chg->arrived != 0) {
516 retval = ctl_add_initiator(dev_chg->wwpn,
517 softc->fe.targ_port, dev_chg->target);
518 } else {
519 retval = ctl_remove_initiator(
520 softc->fe.targ_port, dev_chg->target);
521 }
522
523 if (retval != 0) {
524 printf("%s: could not %s port %d iid %u "
525 "WWPN %#jx!\n", __func__,
526 (dev_chg->arrived != 0) ? "add" :
527 "remove", softc->fe.targ_port,
528 dev_chg->target,
529 (uintmax_t)dev_chg->wwpn);
530 }
531 break;
532 }
533 default:
534 printf("%s: unsupported contract number %ju\n",
535 __func__, (uintmax_t)ac->contract_number);
536 break;
537 }
538 break;
539 }
540 default:
541 break;
542 }
543}
544
545static cam_status
546ctlferegister(struct cam_periph *periph, void *arg)
547{
548 struct ctlfe_softc *bus_softc;
549 struct ctlfe_lun_softc *softc;
550 struct cam_sim *sim;
551 union ccb en_lun_ccb;
552 cam_status status;
553 int i;
554
555 softc = (struct ctlfe_lun_softc *)arg;
556 bus_softc = softc->parent_softc;
557 sim = xpt_path_sim(periph->path);
558
559 TAILQ_INIT(&softc->work_queue);
560 softc->periph = periph;
561
562 callout_init_mtx(&softc->dma_callout, sim->mtx, /*flags*/ 0);
563 periph->softc = softc;
564
565 xpt_setup_ccb(&en_lun_ccb.ccb_h, periph->path, /*priority*/ 1);
566 en_lun_ccb.ccb_h.func_code = XPT_EN_LUN;
567 en_lun_ccb.cel.grp6_len = 0;
568 en_lun_ccb.cel.grp7_len = 0;
569 en_lun_ccb.cel.enable = 1;
570 xpt_action(&en_lun_ccb);
571 status = (en_lun_ccb.ccb_h.status & CAM_STATUS_MASK);
572 if (status != CAM_REQ_CMP) {
573 xpt_print(periph->path, "%s: Enable LUN failed, status 0x%x\n",
574 __func__, en_lun_ccb.ccb_h.status);
575 return (status);
576 }
577
578 status = CAM_REQ_CMP;
579
580 for (i = 0; i < CTLFE_ATIO_PER_LUN; i++) {
581 union ccb *new_ccb;
582
583 new_ccb = (union ccb *)malloc(sizeof(*new_ccb), M_CTLFE,
584 M_ZERO|M_NOWAIT);
585 if (new_ccb == NULL) {
586 status = CAM_RESRC_UNAVAIL;
587 break;
588 }
589 xpt_setup_ccb(&new_ccb->ccb_h, periph->path, /*priority*/ 1);
590 new_ccb->ccb_h.func_code = XPT_ACCEPT_TARGET_IO;
591 new_ccb->ccb_h.cbfcnp = ctlfedone;
592 xpt_action(new_ccb);
593 softc->atios_sent++;
594 status = new_ccb->ccb_h.status;
595 if ((status & CAM_STATUS_MASK) != CAM_REQ_INPROG) {
596 free(new_ccb, M_CTLFE);
597 break;
598 }
599 }
600
601 status = cam_periph_acquire(periph);
602 if ((status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
603 xpt_print(periph->path, "%s: could not acquire reference "
604 "count, status = %#x\n", __func__, status);
605 return (status);
606 }
607
608 if (i == 0) {
609 xpt_print(periph->path, "%s: could not allocate ATIO CCBs, "
610 "status 0x%x\n", __func__, status);
611 return (CAM_REQ_CMP_ERR);
612 }
613
614 for (i = 0; i < CTLFE_IN_PER_LUN; i++) {
615 union ccb *new_ccb;
616
617 new_ccb = (union ccb *)malloc(sizeof(*new_ccb), M_CTLFE,
618 M_ZERO|M_NOWAIT);
619 if (new_ccb == NULL) {
620 status = CAM_RESRC_UNAVAIL;
621 break;
622 }
623
624 xpt_setup_ccb(&new_ccb->ccb_h, periph->path, /*priority*/ 1);
625 new_ccb->ccb_h.func_code = XPT_IMMEDIATE_NOTIFY;
626 new_ccb->ccb_h.cbfcnp = ctlfedone;
627 xpt_action(new_ccb);
628 softc->inots_sent++;
629 status = new_ccb->ccb_h.status;
630 if ((status & CAM_STATUS_MASK) != CAM_REQ_INPROG) {
631 /*
632 * Note that we don't free the CCB here. If the
633 * status is not CAM_REQ_INPROG, then we're
634 * probably talking to a SIM that says it is
635 * target-capable but doesn't support the
636 * XPT_IMMEDIATE_NOTIFY CCB. i.e. it supports the
637 * older API. In that case, it'll call xpt_done()
638 * on the CCB, and we need to free it in our done
639 * routine as a result.
640 */
641 break;
642 }
643 }
644 if ((i == 0)
645 || (status != CAM_REQ_INPROG)) {
646 xpt_print(periph->path, "%s: could not allocate immediate "
647 "notify CCBs, status 0x%x\n", __func__, status);
648 return (CAM_REQ_CMP_ERR);
649 }
650 return (CAM_REQ_CMP);
651}
652
653static void
654ctlfeoninvalidate(struct cam_periph *periph)
655{
656 union ccb en_lun_ccb;
657 cam_status status;
658 struct ctlfe_lun_softc *softc;
659
660 softc = (struct ctlfe_lun_softc *)periph->softc;
661
662 xpt_setup_ccb(&en_lun_ccb.ccb_h, periph->path, /*priority*/ 1);
663 en_lun_ccb.ccb_h.func_code = XPT_EN_LUN;
664 en_lun_ccb.cel.grp6_len = 0;
665 en_lun_ccb.cel.grp7_len = 0;
666 en_lun_ccb.cel.enable = 0;
667 xpt_action(&en_lun_ccb);
668 status = (en_lun_ccb.ccb_h.status & CAM_STATUS_MASK);
669 if (status != CAM_REQ_CMP) {
670 xpt_print(periph->path, "%s: Disable LUN failed, status 0x%x\n",
671 __func__, en_lun_ccb.ccb_h.status);
672 /*
673 * XXX KDM what do we do now?
674 */
675 }
676 xpt_print(periph->path, "LUN removed, %ju ATIOs outstanding, %ju "
677 "INOTs outstanding, %d refs\n", softc->atios_sent -
678 softc->atios_returned, softc->inots_sent -
679 softc->inots_returned, periph->refcount);
680}
681
682static void
683ctlfecleanup(struct cam_periph *periph)
684{
685 struct ctlfe_lun_softc *softc;
686 struct ctlfe_softc *bus_softc;
687
688 xpt_print(periph->path, "%s: Called\n", __func__);
689
690 softc = (struct ctlfe_lun_softc *)periph->softc;
691 bus_softc = softc->parent_softc;
692
693 STAILQ_REMOVE(&bus_softc->lun_softc_list, softc, ctlfe_lun_softc,links);
694
695 /*
696 * XXX KDM is there anything else that needs to be done here?
697 */
698 free(softc, M_CTLFE);
699}
700
701static void
702ctlfestart(struct cam_periph *periph, union ccb *start_ccb)
703{
704 struct ctlfe_lun_softc *softc;
705 struct ccb_hdr *ccb_h;
706
707 softc = (struct ctlfe_lun_softc *)periph->softc;
708
709 softc->ccbs_alloced++;
710
711 ccb_h = TAILQ_FIRST(&softc->work_queue);
712 if (periph->immediate_priority <= periph->pinfo.priority) {
713 panic("shouldn't get to the CCB waiting case!");
714 start_ccb->ccb_h.ccb_type = CTLFE_CCB_WAITING;
715 SLIST_INSERT_HEAD(&periph->ccb_list, &start_ccb->ccb_h,
716 periph_links.sle);
717 periph->immediate_priority = CAM_PRIORITY_NONE;
718 wakeup(&periph->ccb_list);
719 } else if (ccb_h == NULL) {
720 softc->ccbs_freed++;
721 xpt_release_ccb(start_ccb);
722 } else {
723 struct ccb_accept_tio *atio;
724 struct ccb_scsiio *csio;
725 uint8_t *data_ptr;
726 uint32_t dxfer_len;
727 ccb_flags flags;
728 union ctl_io *io;
729 uint8_t scsi_status;
730
731 /* Take the ATIO off the work queue */
732 TAILQ_REMOVE(&softc->work_queue, ccb_h, periph_links.tqe);
733 atio = (struct ccb_accept_tio *)ccb_h;
734 io = (union ctl_io *)ccb_h->io_ptr;
735 csio = &start_ccb->csio;
736
737 flags = atio->ccb_h.flags &
738 (CAM_DIS_DISCONNECT|CAM_TAG_ACTION_VALID|CAM_DIR_MASK);
739
740 if ((io == NULL)
741 || (io->io_hdr.status & CTL_STATUS_MASK) != CTL_STATUS_NONE) {
742 /*
743 * We're done, send status back.
744 */
745 flags |= CAM_SEND_STATUS;
746 if (io == NULL) {
747 scsi_status = SCSI_STATUS_BUSY;
748 csio->sense_len = 0;
749 } else if ((io->io_hdr.status & CTL_STATUS_MASK) ==
750 CTL_CMD_ABORTED) {
751 io->io_hdr.flags &= ~CTL_FLAG_STATUS_QUEUED;
752
753 /*
754 * If this command was aborted, we don't
755 * need to send status back to the SIM.
756 * Just free the CTIO and ctl_io, and
757 * recycle the ATIO back to the SIM.
758 */
759 xpt_print(periph->path, "%s: aborted "
760 "command 0x%04x discarded\n",
761 __func__, io->scsiio.tag_num);
762 ctl_free_io(io);
763 /*
764 * For a wildcard attachment, commands can
765 * come in with a specific target/lun. Reset
766 * the target and LUN fields back to the
767 * wildcard values before we send them back
768 * down to the SIM. The SIM has a wildcard
769 * LUN enabled, not whatever target/lun
770 * these happened to be.
771 */
772 if (softc->flags & CTLFE_LUN_WILDCARD) {
773 atio->ccb_h.target_id =
774 CAM_TARGET_WILDCARD;
775 atio->ccb_h.target_lun =
776 CAM_LUN_WILDCARD;
777 }
778
779 if ((atio->ccb_h.status & CAM_DEV_QFRZN) != 0) {
780 cam_release_devq(periph->path,
781 /*relsim_flags*/0,
782 /*reduction*/0,
783 /*timeout*/0,
784 /*getcount_only*/0);
785 atio->ccb_h.status &= ~CAM_DEV_QFRZN;
786 }
787
788 ccb_h = TAILQ_FIRST(&softc->work_queue);
789
790 if (atio->ccb_h.func_code !=
791 XPT_ACCEPT_TARGET_IO) {
792 xpt_print(periph->path, "%s: func_code "
793 "is %#x\n", __func__,
794 atio->ccb_h.func_code);
795 }
796 start_ccb->ccb_h.func_code = XPT_ABORT;
797 start_ccb->cab.abort_ccb = (union ccb *)atio;
798 start_ccb->ccb_h.cbfcnp = ctlfedone;
799
800 /* Tell the SIM that we've aborted this ATIO */
801 xpt_action(start_ccb);
802 softc->ccbs_freed++;
803 xpt_release_ccb(start_ccb);
804
805 /*
806 * Send the ATIO back down to the SIM.
807 */
808 xpt_action((union ccb *)atio);
809 softc->atios_sent++;
810
811 /*
812 * If we still have work to do, ask for
813 * another CCB. Otherwise, deactivate our
814 * callout.
815 */
816 if (ccb_h != NULL)
817 xpt_schedule(periph, /*priority*/ 1);
818 else
819 callout_stop(&softc->dma_callout);
820
821 return;
822 } else {
823 io->io_hdr.flags &= ~CTL_FLAG_STATUS_QUEUED;
824 scsi_status = io->scsiio.scsi_status;
825 csio->sense_len = io->scsiio.sense_len;
826 }
827 data_ptr = NULL;
828 dxfer_len = 0;
829 if (io == NULL) {
830 printf("%s: tag %04x io is NULL\n", __func__,
831 atio->tag_id);
832 } else {
833#ifdef CTLFEDEBUG
834 printf("%s: tag %04x status %x\n", __func__,
835 atio->tag_id, io->io_hdr.status);
836#endif
837 }
838 csio->sglist_cnt = 0;
839 if (csio->sense_len != 0) {
840 csio->sense_data = io->scsiio.sense_data;
841 flags |= CAM_SEND_SENSE;
842 } else if (scsi_status == SCSI_STATUS_CHECK_COND) {
843 xpt_print(periph->path, "%s: check condition "
844 "with no sense\n", __func__);
845 }
846 } else {
847 struct ctlfe_lun_cmd_info *cmd_info;
848
849 /*
850 * Datamove call, we need to setup the S/G list.
851 * If we pass in a S/G list, the isp(4) driver at
852 * least expects physical/bus addresses.
853 */
854
855 cmd_info = (struct ctlfe_lun_cmd_info *)
856 io->io_hdr.port_priv;
857
858 KASSERT(sizeof(*cmd_info) < CTL_PORT_PRIV_SIZE,
859 ("%s: sizeof(struct ctlfe_lun_cmd_info) %zd < "
860 "CTL_PORT_PRIV_SIZE %d", __func__,
861 sizeof(*cmd_info), CTL_PORT_PRIV_SIZE));
862 io->io_hdr.flags &= ~CTL_FLAG_DMA_QUEUED;
863
864 /*
865 * Need to zero this, in case it has been used for
866 * a previous datamove for this particular I/O.
867 */
868 bzero(cmd_info, sizeof(*cmd_info));
869 scsi_status = 0;
870
871 /*
872 * Set the direction, relative to the initiator.
873 */
874 flags &= ~CAM_DIR_MASK;
875 if ((io->io_hdr.flags & CTL_FLAG_DATA_MASK) ==
876 CTL_FLAG_DATA_IN)
877 flags |= CAM_DIR_IN;
878 else
879 flags |= CAM_DIR_OUT;
880
881 csio->cdb_len = atio->cdb_len;
882
883 if (io->scsiio.kern_sg_entries == 0) {
884 /* No S/G list */
885 data_ptr = io->scsiio.kern_data_ptr;
886 dxfer_len = io->scsiio.kern_data_len;
887 csio->sglist_cnt = 0;
888
889 if (io->io_hdr.flags & CTL_FLAG_BUS_ADDR)
890 flags |= CAM_DATA_PHYS;
891 } else if (io->scsiio.kern_sg_entries <=
892 (sizeof(cmd_info->cam_sglist)/
893 sizeof(cmd_info->cam_sglist[0]))) {
894 /*
895 * S/G list with physical or virtual pointers.
896 * Just populate the CAM S/G list with the
897 * pointers.
898 */
899 int i;
900 struct ctl_sg_entry *ctl_sglist;
901 bus_dma_segment_t *cam_sglist;
902
903 ctl_sglist = (struct ctl_sg_entry *)
904 io->scsiio.kern_data_ptr;
905 cam_sglist = cmd_info->cam_sglist;
906
907 for (i = 0; i < io->scsiio.kern_sg_entries;i++){
908 cam_sglist[i].ds_addr =
909 (bus_addr_t)ctl_sglist[i].addr;
910 cam_sglist[i].ds_len =
911 ctl_sglist[i].len;
912 }
913 csio->sglist_cnt = io->scsiio.kern_sg_entries;
914 flags |= CAM_SCATTER_VALID;
915 if (io->io_hdr.flags & CTL_FLAG_BUS_ADDR)
916 flags |= CAM_SG_LIST_PHYS;
917 else
918 flags &= ~CAM_SG_LIST_PHYS;
919 data_ptr = (uint8_t *)cam_sglist;
920 dxfer_len = io->scsiio.kern_data_len;
921 } else {
922 /* S/G list with virtual pointers */
923 struct ctl_sg_entry *sglist;
924 int *ti;
925
926 /*
927 * XXX KDM this is a temporary hack. The
928 * isp(4) driver can't deal with S/G lists
929 * with virtual pointers, so we need to
930 * go through and send down one virtual
931 * pointer at a time.
932 */
933 sglist = (struct ctl_sg_entry *)
934 io->scsiio.kern_data_ptr;
935 ti = &cmd_info->cur_transfer_index;
936 data_ptr = sglist[*ti].addr;
937 dxfer_len = sglist[*ti].len;
938 csio->sglist_cnt = 0;
939 cmd_info->flags |= CTLFE_CMD_PIECEWISE;
940 (*ti)++;
941 }
942
943 io->scsiio.ext_data_filled += dxfer_len;
944
945 if (io->scsiio.ext_data_filled >
946 io->scsiio.kern_total_len) {
947 xpt_print(periph->path, "%s: tag 0x%04x "
948 "fill len %u > total %u\n",
949 __func__, io->scsiio.tag_num,
950 io->scsiio.ext_data_filled,
951 io->scsiio.kern_total_len);
952 }
953 }
954
955#ifdef CTLFEDEBUG
956 printf("%s: %s: tag %04x flags %x ptr %p len %u\n", __func__,
957 (flags & CAM_SEND_STATUS) ? "done" : "datamove",
958 atio->tag_id, flags, data_ptr, dxfer_len);
959#endif
960
961 /*
962 * Valid combinations:
963 * - CAM_SEND_STATUS, SCATTER_VALID = 0, dxfer_len = 0,
964 * sglist_cnt = 0
965 * - CAM_SEND_STATUS = 0, SCATTER_VALID = 0, dxfer_len != 0,
966 * sglist_cnt = 0
967 * - CAM_SEND_STATUS = 0, SCATTER_VALID, dxfer_len != 0,
968 * sglist_cnt != 0
969 */
970#ifdef CTLFEDEBUG
971 if (((flags & CAM_SEND_STATUS)
972 && (((flags & CAM_SCATTER_VALID) != 0)
973 || (dxfer_len != 0)
974 || (csio->sglist_cnt != 0)))
975 || (((flags & CAM_SEND_STATUS) == 0)
976 && (dxfer_len == 0))
977 || ((flags & CAM_SCATTER_VALID)
978 && (csio->sglist_cnt == 0))
979 || (((flags & CAM_SCATTER_VALID) == 0)
980 && (csio->sglist_cnt != 0))) {
981 printf("%s: tag %04x cdb %02x flags %#x dxfer_len "
982 "%d sg %u\n", __func__, atio->tag_id,
983 atio->cdb_io.cdb_bytes[0], flags, dxfer_len,
984 csio->sglist_cnt);
985 if (io != NULL) {
986 printf("%s: tag %04x io status %#x\n", __func__,
987 atio->tag_id, io->io_hdr.status);
988 } else {
989 printf("%s: tag %04x no associated io\n",
990 __func__, atio->tag_id);
991 }
992 }
993#endif
994 cam_fill_ctio(csio,
995 /*retries*/ 2,
996 ctlfedone,
997 flags,
998 (flags & CAM_TAG_ACTION_VALID) ?
999 MSG_SIMPLE_Q_TAG : 0,
1000 atio->tag_id,
1001 atio->init_id,
1002 scsi_status,
1003 /*data_ptr*/ data_ptr,
1004 /*dxfer_len*/ dxfer_len,
1005 /*timeout*/ 5 * 1000);
1006 start_ccb->ccb_h.ccb_atio = atio;
1007 if (((flags & CAM_SEND_STATUS) == 0)
1008 && (io != NULL))
1009 io->io_hdr.flags |= CTL_FLAG_DMA_INPROG;
1010
1011 softc->ctios_sent++;
1012
1013 xpt_action(start_ccb);
1014
1015 if ((atio->ccb_h.status & CAM_DEV_QFRZN) != 0) {
1016 cam_release_devq(periph->path,
1017 /*relsim_flags*/0,
1018 /*reduction*/0,
1019 /*timeout*/0,
1020 /*getcount_only*/0);
1021 atio->ccb_h.status &= ~CAM_DEV_QFRZN;
1022 }
1023
1024 ccb_h = TAILQ_FIRST(&softc->work_queue);
1025 }
1026 /*
1027 * If we still have work to do, ask for another CCB. Otherwise,
1028 * deactivate our callout.
1029 */
1030 if (ccb_h != NULL)
1031 xpt_schedule(periph, /*priority*/ 1);
1032 else
1033 callout_stop(&softc->dma_callout);
1034}
1035
1036static void
1037ctlfe_free_ccb(struct cam_periph *periph, union ccb *ccb)
1038{
1039 struct ctlfe_lun_softc *softc;
1040
1041 softc = (struct ctlfe_lun_softc *)periph->softc;
1042
1043 switch (ccb->ccb_h.func_code) {
1044 case XPT_ACCEPT_TARGET_IO:
1045 softc->atios_returned++;
1046 break;
1047 case XPT_IMMEDIATE_NOTIFY:
1048 case XPT_NOTIFY_ACKNOWLEDGE:
1049 softc->inots_returned++;
1050 break;
1051 default:
1052 break;
1053 }
1054
1055 free(ccb, M_CTLFE);
1056
1057 KASSERT(softc->atios_returned <= softc->atios_sent, ("%s: "
1058 "atios_returned %ju > atios_sent %ju", __func__,
1059 softc->atios_returned, softc->atios_sent));
1060 KASSERT(softc->inots_returned <= softc->inots_sent, ("%s: "
1061 "inots_returned %ju > inots_sent %ju", __func__,
1062 softc->inots_returned, softc->inots_sent));
1063
1064 /*
1065 * If we have received all of our CCBs, we can release our
1066 * reference on the peripheral driver. It will probably go away
1067 * now.
1068 */
1069 if ((softc->atios_returned == softc->atios_sent)
1070 && (softc->inots_returned == softc->inots_sent)) {
1071 cam_periph_release_locked(periph);
1072 }
1073}
1074
1075static void
1076ctlfedone(struct cam_periph *periph, union ccb *done_ccb)
1077{
1078 struct ctlfe_lun_softc *softc;
1079 struct ctlfe_softc *bus_softc;
1080
1081#ifdef CTLFE_DEBUG
1082 printf("%s: entered, func_code = %#x, type = %#lx\n", __func__,
1083 done_ccb->ccb_h.func_code, done_ccb->ccb_h.ccb_type);
1084#endif
1085
1086 softc = (struct ctlfe_lun_softc *)periph->softc;
1087 bus_softc = softc->parent_softc;
1088
1089 if (done_ccb->ccb_h.ccb_type == CTLFE_CCB_WAITING) {
1090 panic("shouldn't get to the CCB waiting case!");
1091 wakeup(&done_ccb->ccb_h.cbfcnp);
1092 return;
1093 }
1094
1095 /*
1096 * If the peripheral is invalid, ATIOs and immediate notify CCBs
1097 * need to be freed. Most of the ATIOs and INOTs that come back
1098 * will be CCBs that are being returned from the SIM as a result of
1099 * our disabling the LUN.
1100 *
1101 * Other CCB types are handled in their respective cases below.
1102 */
1103 if (periph->flags & CAM_PERIPH_INVALID) {
1104 switch (done_ccb->ccb_h.func_code) {
1105 case XPT_ACCEPT_TARGET_IO:
1106 case XPT_IMMEDIATE_NOTIFY:
1107 case XPT_NOTIFY_ACKNOWLEDGE:
1108 ctlfe_free_ccb(periph, done_ccb);
1109 return;
1110 default:
1111 break;
1112 }
1113
1114 }
1115 switch (done_ccb->ccb_h.func_code) {
1116 case XPT_ACCEPT_TARGET_IO: {
1117 union ctl_io *io;
1118 struct ccb_accept_tio *atio;
1119
1120 atio = &done_ccb->atio;
1121
1122 softc->atios_returned++;
1123
1124 /*
1125 * Allocate a ctl_io, pass it to CTL, and wait for the
1126 * datamove or done.
1127 */
1128 io = ctl_alloc_io(bus_softc->fe.ctl_pool_ref);
1129 if (io == NULL) {
1130 atio->ccb_h.flags &= ~CAM_DIR_MASK;
1131 atio->ccb_h.flags |= CAM_DIR_NONE;
1132
1133 printf("%s: ctl_alloc_io failed!\n", __func__);
1134
1135 /*
1136 * XXX KDM need to set SCSI_STATUS_BUSY, but there
1137 * is no field in the ATIO structure to do that,
1138 * and we aren't able to allocate a ctl_io here.
1139 * What to do?
1140 */
1141 atio->sense_len = 0;
1142 done_ccb->ccb_h.io_ptr = NULL;
1143 TAILQ_INSERT_TAIL(&softc->work_queue, &atio->ccb_h,
1144 periph_links.tqe);
1145 xpt_schedule(periph, /*priority*/ 1);
1146 break;
1147 }
1148 ctl_zero_io(io);
1149
1150 /* Save pointers on both sides */
1151 io->io_hdr.ctl_private[CTL_PRIV_FRONTEND].ptr = done_ccb;
1152 done_ccb->ccb_h.io_ptr = io;
1153
1154 /*
1155 * Only SCSI I/O comes down this path, resets, etc. come
1156 * down the immediate notify path below.
1157 */
1158 io->io_hdr.io_type = CTL_IO_SCSI;
1159 io->io_hdr.nexus.initid.id = atio->init_id;
1160 io->io_hdr.nexus.targ_port = bus_softc->fe.targ_port;
1161 io->io_hdr.nexus.targ_target.id = atio->ccb_h.target_id;
1162 io->io_hdr.nexus.targ_lun = atio->ccb_h.target_lun;
1163 io->scsiio.tag_num = atio->tag_id;
1164 switch (atio->tag_action) {
1165 case CAM_TAG_ACTION_NONE:
1166 io->scsiio.tag_type = CTL_TAG_UNTAGGED;
1167 break;
1168 case MSG_SIMPLE_TASK:
1169 io->scsiio.tag_type = CTL_TAG_SIMPLE;
1170 break;
1171 case MSG_HEAD_OF_QUEUE_TASK:
1172 io->scsiio.tag_type = CTL_TAG_HEAD_OF_QUEUE;
1173 break;
1174 case MSG_ORDERED_TASK:
1175 io->scsiio.tag_type = CTL_TAG_ORDERED;
1176 break;
1177 case MSG_ACA_TASK:
1178 io->scsiio.tag_type = CTL_TAG_ACA;
1179 break;
1180 default:
1181 io->scsiio.tag_type = CTL_TAG_UNTAGGED;
1182 printf("%s: unhandled tag type %#x!!\n", __func__,
1183 atio->tag_action);
1184 break;
1185 }
1186 if (atio->cdb_len > sizeof(io->scsiio.cdb)) {
1187 printf("%s: WARNING: CDB len %d > ctl_io space %zd\n",
1188 __func__, atio->cdb_len, sizeof(io->scsiio.cdb));
1189 }
1190 io->scsiio.cdb_len = min(atio->cdb_len, sizeof(io->scsiio.cdb));
1191 bcopy(atio->cdb_io.cdb_bytes, io->scsiio.cdb,
1192 io->scsiio.cdb_len);
1193
1194#ifdef CTLFEDEBUG
1195 printf("%s: %ju:%d:%ju:%d: tag %04x CDB %02x\n", __func__,
1196 (uintmax_t)io->io_hdr.nexus.initid.id,
1197 io->io_hdr.nexus.targ_port,
1198 (uintmax_t)io->io_hdr.nexus.targ_target.id,
1199 io->io_hdr.nexus.targ_lun,
1200 io->scsiio.tag_num, io->scsiio.cdb[0]);
1201#endif
1202
1203 ctl_queue(io);
1204 break;
1205 }
1206 case XPT_CONT_TARGET_IO: {
1207 struct ccb_accept_tio *atio;
1208 union ctl_io *io;
1209
1210 atio = (struct ccb_accept_tio *)done_ccb->ccb_h.ccb_atio;
1211 io = (union ctl_io *)atio->ccb_h.io_ptr;
1212
1213 softc->ctios_returned++;
1214#ifdef CTLFEDEBUG
1215 printf("%s: got XPT_CONT_TARGET_IO tag %#x flags %#x\n",
1216 __func__, atio->tag_id, done_ccb->ccb_h.flags);
1217#endif
1218 /*
1219 * If we were sending status back to the initiator, free up
1220 * resources. If we were doing a datamove, call the
1221 * datamove done routine.
1222 */
1223 if (done_ccb->ccb_h.flags & CAM_SEND_STATUS) {
1224 softc->ccbs_freed++;
1225 xpt_release_ccb(done_ccb);
1226 ctl_free_io(io);
1227 /*
1228 * For a wildcard attachment, commands can come in
1229 * with a specific target/lun. Reset the target
1230 * and LUN fields back to the wildcard values before
1231 * we send them back down to the SIM. The SIM has
1232 * a wildcard LUN enabled, not whatever target/lun
1233 * these happened to be.
1234 */
1235 if (softc->flags & CTLFE_LUN_WILDCARD) {
1236 atio->ccb_h.target_id = CAM_TARGET_WILDCARD;
1237 atio->ccb_h.target_lun = CAM_LUN_WILDCARD;
1238 }
1239 if (periph->flags & CAM_PERIPH_INVALID) {
1240 ctlfe_free_ccb(periph, (union ccb *)atio);
1241 return;
1242 } else {
1243 xpt_action((union ccb *)atio);
1244 softc->atios_sent++;
1245 }
1246 } else {
1247 struct ctlfe_lun_cmd_info *cmd_info;
1248 struct ccb_scsiio *csio;
1249
1250 csio = &done_ccb->csio;
1251 cmd_info = (struct ctlfe_lun_cmd_info *)
1252 io->io_hdr.port_priv;
1253
1254 io->io_hdr.flags &= ~CTL_FLAG_DMA_INPROG;
1255
1256 io->scsiio.ext_data_len += csio->dxfer_len;
1257 if (io->scsiio.ext_data_len >
1258 io->scsiio.kern_total_len) {
1259 xpt_print(periph->path, "%s: tag 0x%04x "
1260 "done len %u > total %u sent %u\n",
1261 __func__, io->scsiio.tag_num,
1262 io->scsiio.ext_data_len,
1263 io->scsiio.kern_total_len,
1264 io->scsiio.ext_data_filled);
1265 }
1266 /*
1267 * Translate CAM status to CTL status. Success
1268 * does not change the overall, ctl_io status. In
1269 * that case we just set port_status to 0. If we
1270 * have a failure, though, set a data phase error
1271 * for the overall ctl_io.
1272 */
1273 switch (done_ccb->ccb_h.status & CAM_STATUS_MASK) {
1274 case CAM_REQ_CMP:
1275 io->io_hdr.port_status = 0;
1276 break;
1277 default:
1278 /*
1279 * XXX KDM the isp(4) driver doesn't really
1280 * seem to send errors back for data
1281 * transfers that I can tell. There is one
1282 * case where it'll send CAM_REQ_CMP_ERR,
1283 * but probably not that many more cases.
1284 * So set a generic data phase error here,
1285 * like the SXP driver sets.
1286 */
1287 io->io_hdr.port_status = 0xbad1;
1288 ctl_set_data_phase_error(&io->scsiio);
1289 /*
1290 * XXX KDM figure out residual.
1291 */
1292 break;
1293 }
1294 /*
1295 * If we had to break this S/G list into multiple
1296 * pieces, figure out where we are in the list, and
1297 * continue sending pieces if necessary.
1298 */
1299 if ((cmd_info->flags & CTLFE_CMD_PIECEWISE)
1300 && (io->io_hdr.port_status == 0)
1301 && (cmd_info->cur_transfer_index <
1302 io->scsiio.kern_sg_entries)) {
1303 struct ctl_sg_entry *sglist;
1304 ccb_flags flags;
1305 uint8_t scsi_status;
1306 uint8_t *data_ptr;
1307 uint32_t dxfer_len;
1308 int *ti;
1309
1310 sglist = (struct ctl_sg_entry *)
1311 io->scsiio.kern_data_ptr;
1312 ti = &cmd_info->cur_transfer_index;
1313 flags = atio->ccb_h.flags &
1314 (CAM_DIS_DISCONNECT|
1315 CAM_TAG_ACTION_VALID|
1316 CAM_DIR_MASK);
1317
1318 /*
1319 * Set the direction, relative to the initiator.
1320 */
1321 flags &= ~CAM_DIR_MASK;
1322 if ((io->io_hdr.flags & CTL_FLAG_DATA_MASK) ==
1323 CTL_FLAG_DATA_IN)
1324 flags |= CAM_DIR_IN;
1325 else
1326 flags |= CAM_DIR_OUT;
1327
1328 data_ptr = sglist[*ti].addr;
1329 dxfer_len = sglist[*ti].len;
1330 (*ti)++;
1331
1332 scsi_status = 0;
1333
1334 if (((flags & CAM_SEND_STATUS) == 0)
1335 && (dxfer_len == 0)) {
1336 printf("%s: tag %04x no status or "
1337 "len cdb = %02x\n", __func__,
1338 atio->tag_id,
1339 atio->cdb_io.cdb_bytes[0]);
1340 printf("%s: tag %04x io status %#x\n",
1341 __func__, atio->tag_id,
1342 io->io_hdr.status);
1343 }
1344
1345 cam_fill_ctio(csio,
1346 /*retries*/ 2,
1347 ctlfedone,
1348 flags,
1349 (flags & CAM_TAG_ACTION_VALID) ?
1350 MSG_SIMPLE_Q_TAG : 0,
1351 atio->tag_id,
1352 atio->init_id,
1353 scsi_status,
1354 /*data_ptr*/ data_ptr,
1355 /*dxfer_len*/ dxfer_len,
1356 /*timeout*/ 5 * 1000);
1357
1358 csio->resid = 0;
1359 csio->ccb_h.ccb_atio = atio;
1360 io->io_hdr.flags |= CTL_FLAG_DMA_INPROG;
1361 softc->ctios_sent++;
1362 xpt_action((union ccb *)csio);
1363 } else {
1364 /*
1365 * Release the CTIO. The ATIO will be sent back
1366 * down to the SIM once we send status.
1367 */
1368 softc->ccbs_freed++;
1369 xpt_release_ccb(done_ccb);
1370
1371 /* Call the backend move done callback */
1372 io->scsiio.be_move_done(io);
1373 }
1374 }
1375 break;
1376 }
1377 case XPT_IMMEDIATE_NOTIFY: {
1378 union ctl_io *io;
1379 struct ccb_immediate_notify *inot;
1380 cam_status status;
1381 int frozen;
1382
1383 inot = &done_ccb->cin1;
1384
1385 softc->inots_returned++;
1386
1387 frozen = (done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0;
1388
1389 printf("%s: got XPT_IMMEDIATE_NOTIFY status %#x tag %#x "
1390 "seq %#x\n", __func__, inot->ccb_h.status,
1391 inot->tag_id, inot->seq_id);
1392
1393 io = ctl_alloc_io(bus_softc->fe.ctl_pool_ref);
1394 if (io != NULL) {
1395 int send_ctl_io;
1396
1397 send_ctl_io = 1;
1398
1399 ctl_zero_io(io);
1400 io->io_hdr.io_type = CTL_IO_TASK;
1401 io->io_hdr.ctl_private[CTL_PRIV_FRONTEND].ptr =done_ccb;
1402 inot->ccb_h.io_ptr = io;
1403 io->io_hdr.nexus.initid.id = inot->initiator_id;
1404 io->io_hdr.nexus.targ_port = bus_softc->fe.targ_port;
1405 io->io_hdr.nexus.targ_target.id = inot->ccb_h.target_id;
1406 io->io_hdr.nexus.targ_lun = inot->ccb_h.target_lun;
1407 /* XXX KDM should this be the tag_id? */
1408 io->taskio.tag_num = inot->seq_id;
1409
1410 status = inot->ccb_h.status & CAM_STATUS_MASK;
1411 switch (status) {
1412 case CAM_SCSI_BUS_RESET:
1413 io->taskio.task_action = CTL_TASK_BUS_RESET;
1414 break;
1415 case CAM_BDR_SENT:
1416 io->taskio.task_action = CTL_TASK_TARGET_RESET;
1417 break;
1418 case CAM_MESSAGE_RECV:
1419 switch (inot->arg) {
1420 case MSG_ABORT_TASK_SET:
1421 /*
1422 * XXX KDM this isn't currently
1423 * supported by CTL. It ends up
1424 * being a no-op.
1425 */
1426 io->taskio.task_action =
1427 CTL_TASK_ABORT_TASK_SET;
1428 break;
1429 case MSG_TARGET_RESET:
1430 io->taskio.task_action =
1431 CTL_TASK_TARGET_RESET;
1432 break;
1433 case MSG_ABORT_TASK:
1434 io->taskio.task_action =
1435 CTL_TASK_ABORT_TASK;
1436 break;
1437 case MSG_LOGICAL_UNIT_RESET:
1438 io->taskio.task_action =
1439 CTL_TASK_LUN_RESET;
1440 break;
1441 case MSG_CLEAR_TASK_SET:
1442 /*
1443 * XXX KDM this isn't currently
1444 * supported by CTL. It ends up
1445 * being a no-op.
1446 */
1447 io->taskio.task_action =
1448 CTL_TASK_CLEAR_TASK_SET;
1449 break;
1450 case MSG_CLEAR_ACA:
1451 io->taskio.task_action =
1452 CTL_TASK_CLEAR_ACA;
1453 break;
1454 case MSG_NOOP:
1455 send_ctl_io = 0;
1456 break;
1457 default:
1458 xpt_print(periph->path, "%s: "
1459 "unsupported message 0x%x\n",
1460 __func__, inot->arg);
1461 send_ctl_io = 0;
1462 break;
1463 }
1464 break;
1465 case CAM_REQ_ABORTED:
1466 /*
1467 * This request was sent back by the driver.
1468 * XXX KDM what do we do here?
1469 */
1470 send_ctl_io = 0;
1471 break;
1472 case CAM_REQ_INVALID:
1473 case CAM_PROVIDE_FAIL:
1474 default:
1475 /*
1476 * We should only get here if we're talking
1477 * to a talking to a SIM that is target
1478 * capable but supports the old API. In
1479 * that case, we need to just free the CCB.
1480 * If we actually send a notify acknowledge,
1481 * it will send that back with an error as
1482 * well.
1483 */
1484
1485 if ((status != CAM_REQ_INVALID)
1486 && (status != CAM_PROVIDE_FAIL))
1487 xpt_print(periph->path, "%s: "
1488 "unsupported CAM status "
1489 "0x%x\n", __func__, status);
1490
1491 ctl_free_io(io);
1492 ctlfe_free_ccb(periph, done_ccb);
1493
1494 return;
1495 }
1496 if (send_ctl_io != 0) {
1497 ctl_queue(io);
1498 } else {
1499 ctl_free_io(io);
1500 done_ccb->ccb_h.status = CAM_REQ_INPROG;
1501 done_ccb->ccb_h.func_code =
1502 XPT_NOTIFY_ACKNOWLEDGE;
1503 xpt_action(done_ccb);
1504 }
1505 } else {
1506 xpt_print(periph->path, "%s: could not allocate "
1507 "ctl_io for immediate notify!\n", __func__);
1508 /* requeue this to the adapter */
1509 done_ccb->ccb_h.status = CAM_REQ_INPROG;
1510 done_ccb->ccb_h.func_code = XPT_NOTIFY_ACKNOWLEDGE;
1511 xpt_action(done_ccb);
1512 }
1513
1514 if (frozen != 0) {
1515 cam_release_devq(periph->path,
1516 /*relsim_flags*/ 0,
1517 /*opening reduction*/ 0,
1518 /*timeout*/ 0,
1519 /*getcount_only*/ 0);
1520 }
1521 break;
1522 }
1523 case XPT_NOTIFY_ACKNOWLEDGE:
1524 /*
1525 * Queue this back down to the SIM as an immediate notify.
1526 */
1527 done_ccb->ccb_h.func_code = XPT_IMMEDIATE_NOTIFY;
1528 xpt_action(done_ccb);
1529 softc->inots_sent++;
1530 break;
1531 case XPT_ABORT:
1532 /*
1533 * XPT_ABORT is an immediate CCB, we shouldn't get here.
1534 */
1535 panic("%s: XPT_ABORT CCB returned!", __func__);
1536 break;
1537 case XPT_SET_SIM_KNOB:
1538 case XPT_GET_SIM_KNOB:
1539 break;
1540 default:
1541 panic("%s: unexpected CCB type %#x", __func__,
1542 done_ccb->ccb_h.func_code);
1543 break;
1544 }
1545}
1546
1547static void
1548ctlfe_onoffline(void *arg, int online)
1549{
1550 struct ctlfe_softc *bus_softc;
1551 union ccb *ccb;
1552 cam_status status;
1553 struct cam_path *path;
1554 struct cam_sim *sim;
1555 int set_wwnn;
1556
1557 bus_softc = (struct ctlfe_softc *)arg;
1558
1559 set_wwnn = 0;
1560
1561 status = xpt_create_path(&path, /*periph*/ NULL, bus_softc->path_id,
1562 CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD);
1563 if (status != CAM_REQ_CMP) {
1564 printf("%s: unable to create path!\n", __func__);
1565 return;
1566 }
1567 ccb = (union ccb *)malloc(sizeof(*ccb), M_TEMP, M_WAITOK | M_ZERO);
1568 if (ccb == NULL) {
1569 printf("%s: unable to malloc CCB!\n", __func__);
1570 xpt_free_path(path);
1571 return;
1572 }
1573 xpt_setup_ccb(&ccb->ccb_h, path, /*priority*/ 1);
1574
1575 sim = xpt_path_sim(path);
1576
1577 /*
1578 * Copan WWN format:
1579 *
1580 * Bits 63-60: 0x5 NAA, IEEE registered name
1581 * Bits 59-36: 0x000ED5 IEEE Company name assigned to Copan
1582 * Bits 35-12: Copan SSN (Sequential Serial Number)
1583 * Bits 11-8: Type of port:
1584 * 1 == N-Port
1585 * 2 == F-Port
1586 * 3 == NL-Port
1587 * Bits 7-0: 0 == Node Name, >0 == Port Number
1588 */
1589
1590 if (online != 0) {
1591
1592 ccb->ccb_h.func_code = XPT_GET_SIM_KNOB;
1593
1594 CAM_SIM_LOCK(sim);
1595
1596 xpt_action(ccb);
1597
1598 CAM_SIM_UNLOCK(sim);
1599
1600 if ((ccb->knob.xport_specific.valid & KNOB_VALID_ADDRESS) != 0){
1601#ifdef RANDOM_WWNN
1602 uint64_t random_bits;
1603#endif
1604
1605 printf("%s: %s current WWNN %#jx\n", __func__,
1606 bus_softc->port_name,
1607 ccb->knob.xport_specific.fc.wwnn);
1608 printf("%s: %s current WWPN %#jx\n", __func__,
1609 bus_softc->port_name,
1610 ccb->knob.xport_specific.fc.wwpn);
1611
1612#ifdef RANDOM_WWNN
1613 arc4rand(&random_bits, sizeof(random_bits), 0);
1614#endif
1615
1616 /*
1617 * XXX KDM this is a bit of a kludge for now. We
1618 * take the current WWNN/WWPN from the card, and
1619 * replace the company identifier and the NL-Port
1620 * indicator and the port number (for the WWPN).
1621 * This should be replaced later with ddb_GetWWNN,
1622 * or possibly a more centralized scheme. (It
1623 * would be nice to have the WWNN/WWPN for each
1624 * port stored in the ctl_frontend structure.)
1625 */
1626#ifdef RANDOM_WWNN
1627 ccb->knob.xport_specific.fc.wwnn =
1628 (random_bits &
1629 0x0000000fffffff00ULL) |
1630 /* Company ID */ 0x5000ED5000000000ULL |
1631 /* NL-Port */ 0x0300;
1632 ccb->knob.xport_specific.fc.wwpn =
1633 (random_bits &
1634 0x0000000fffffff00ULL) |
1635 /* Company ID */ 0x5000ED5000000000ULL |
1636 /* NL-Port */ 0x3000 |
1637 /* Port Num */ (bus_softc->fe.targ_port & 0xff);
1638
1639 /*
1640 * This is a bit of an API break/reversal, but if
1641 * we're doing the random WWNN that's a little
1642 * different anyway. So record what we're actually
1643 * using with the frontend code so it's reported
1644 * accurately.
1645 */
1646 bus_softc->fe.wwnn =
1647 ccb->knob.xport_specific.fc.wwnn;
1648 bus_softc->fe.wwpn =
1649 ccb->knob.xport_specific.fc.wwpn;
1650 set_wwnn = 1;
1651#else /* RANDOM_WWNN */
1652 /*
1653 * If the user has specified a WWNN/WWPN, send them
1654 * down to the SIM. Otherwise, record what the SIM
1655 * has reported.
1656 */
1657 if ((bus_softc->fe.wwnn != 0)
1658 && (bus_softc->fe.wwpn != 0)) {
1659 ccb->knob.xport_specific.fc.wwnn =
1660 bus_softc->fe.wwnn;
1661 ccb->knob.xport_specific.fc.wwpn =
1662 bus_softc->fe.wwpn;
1663 set_wwnn = 1;
1664 } else {
1665 bus_softc->fe.wwnn =
1666 ccb->knob.xport_specific.fc.wwnn;
1667 bus_softc->fe.wwpn =
1668 ccb->knob.xport_specific.fc.wwpn;
1669 }
1670#endif /* RANDOM_WWNN */
1671
1672
1673 if (set_wwnn != 0) {
1674 printf("%s: %s new WWNN %#jx\n", __func__,
1675 bus_softc->port_name,
1676 ccb->knob.xport_specific.fc.wwnn);
1677 printf("%s: %s new WWPN %#jx\n", __func__,
1678 bus_softc->port_name,
1679 ccb->knob.xport_specific.fc.wwpn);
1680 }
1681 } else {
1682 printf("%s: %s has no valid WWNN/WWPN\n", __func__,
1683 bus_softc->port_name);
1684 }
1685 }
1686 ccb->ccb_h.func_code = XPT_SET_SIM_KNOB;
1687 ccb->knob.xport_specific.valid = KNOB_VALID_ROLE;
1688 if (set_wwnn != 0)
1689 ccb->knob.xport_specific.valid |= KNOB_VALID_ADDRESS;
1690
1691 if (online != 0)
1692 ccb->knob.xport_specific.fc.role = KNOB_ROLE_TARGET;
1693 else
1694 ccb->knob.xport_specific.fc.role = KNOB_ROLE_NONE;
1695
1696
1697 CAM_SIM_LOCK(sim);
1698
1699 xpt_action(ccb);
1700
1701 CAM_SIM_UNLOCK(sim);
1702
1703 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
1704 printf("%s: SIM %s (path id %d) target %s failed with "
1705 "status %#x\n",
1706 __func__, bus_softc->port_name, bus_softc->path_id,
1707 (online != 0) ? "enable" : "disable",
1708 ccb->ccb_h.status);
1709 } else {
1710 printf("%s: SIM %s (path id %d) target %s succeeded\n",
1711 __func__, bus_softc->port_name, bus_softc->path_id,
1712 (online != 0) ? "enable" : "disable");
1713 }
1714
1715 free(ccb, M_TEMP);
1716 xpt_free_path(path);
1717
1718 return;
1719}
1720
1721static void
1722ctlfe_online(void *arg)
1723{
1724 ctlfe_onoffline(arg, /*online*/ 1);
1725}
1726
1727static void
1728ctlfe_offline(void *arg)
1729{
1730 ctlfe_onoffline(arg, /*online*/ 0);
1731}
1732
1733static int
1734ctlfe_targ_enable(void *arg, struct ctl_id targ_id)
1735{
1736 return (0);
1737}
1738
1739static int
1740ctlfe_targ_disable(void *arg, struct ctl_id targ_id)
1741{
1742 return (0);
1743}
1744
1745/*
1746 * This will get called to enable a LUN on every bus that is attached to
1747 * CTL. So we only need to create a path/periph for this particular bus.
1748 */
1749static int
1750ctlfe_lun_enable(void *arg, struct ctl_id targ_id, int lun_id)
1751{
1752 struct ctlfe_softc *bus_softc;
1753 struct ctlfe_lun_softc *softc;
1754 struct cam_path *path;
1755 struct cam_periph *periph;
1756 struct cam_sim *sim;
1757 cam_status status;
1758
1759
1760 bus_softc = (struct ctlfe_softc *)arg;
1761
1762 status = xpt_create_path_unlocked(&path, /*periph*/ NULL,
1763 bus_softc->path_id,
1764 targ_id.id,
1765 lun_id);
1766 /* XXX KDM need some way to return status to CTL here? */
1767 if (status != CAM_REQ_CMP) {
1768 printf("%s: could not create path, status %#x\n", __func__,
1769 status);
1770 return (1);
1771 }
1772
1773 softc = malloc(sizeof(*softc), M_CTLFE, M_WAITOK | M_ZERO);
1774 if (softc == NULL) {
1775 printf("%s: could not allocate %zd bytes for softc\n",
1776 __func__, sizeof(*softc));
1777 xpt_free_path(path);
1778 return (1);
1779 }
1780 sim = xpt_path_sim(path);
1781 mtx_lock(sim->mtx);
1782 periph = cam_periph_find(path, "ctl");
1783 if (periph != NULL) {
1784 /* We've already got a periph, no need to alloc a new one. */
1785 xpt_free_path(path);
1786 free(softc, M_CTLFE);
1787 mtx_unlock(sim->mtx);
1788 return (0);
1789 }
1790
1791 softc->parent_softc = bus_softc;
1792 STAILQ_INSERT_TAIL(&bus_softc->lun_softc_list, softc, links);
1793
1794 status = cam_periph_alloc(ctlferegister,
1795 ctlfeoninvalidate,
1796 ctlfecleanup,
1797 ctlfestart,
1798 "ctl",
1799 CAM_PERIPH_BIO,
1800 path,
1801 ctlfeasync,
1802 0,
1803 softc);
1804
1805 mtx_unlock(sim->mtx);
1806
1807 xpt_free_path(path);
1808
1809 return (0);
1810}
1811
1812/*
1813 * XXX KDM we disable LUN removal here. The problem is that the isp(4)
1814 * driver doesn't currently handle LUN removal properly. We need to keep
1815 * enough state here at the peripheral level even after LUNs have been
1816 * removed inside CTL.
1817 *
1818 * Once the isp(4) driver is fixed, this can be re-enabled.
1819 */
1820static int
1821ctlfe_lun_disable(void *arg, struct ctl_id targ_id, int lun_id)
1822{
1823#ifdef NOTYET
1824 struct ctlfe_softc *softc;
1825 struct ctlfe_lun_softc *lun_softc;
1826
1827 softc = (struct ctlfe_softc *)arg;
1828
1829 mtx_lock(softc->sim->mtx);
1830 STAILQ_FOREACH(lun_softc, &softc->lun_softc_list, links) {
1831 struct cam_path *path;
1832
1833 path = lun_softc->periph->path;
1834
1835 if ((xpt_path_target_id(path) == targ_id.id)
1836 && (xpt_path_lun_id(path) == lun_id)) {
1837 break;
1838 }
1839 }
1840 if (lun_softc == NULL) {
1841 mtx_unlock(softc->sim->mtx);
1842 printf("%s: can't find target %d lun %d\n", __func__,
1843 targ_id.id, lun_id);
1844 return (1);
1845 }
1846
1847 cam_periph_invalidate(lun_softc->periph);
1848
1849 mtx_unlock(softc->sim->mtx);
1850#endif
1851
1852 return (0);
1853}
1854
1855static void
1856ctlfe_dump_sim(struct cam_sim *sim)
1857{
1858 int i;
1859
1860 printf("%s%d: max tagged openings: %d, max dev openings: %d\n",
1861 sim->sim_name, sim->unit_number,
1862 sim->max_tagged_dev_openings, sim->max_dev_openings);
1863 printf("%s%d: max_ccbs: %u, ccb_count: %u\n",
1864 sim->sim_name, sim->unit_number,
1865 sim->max_ccbs, sim->ccb_count);
1866 printf("%s%d: ccb_freeq is %sempty\n",
1867 sim->sim_name, sim->unit_number,
1868 (SLIST_FIRST(&sim->ccb_freeq) == NULL) ? "" : "NOT ");
1869 printf("%s%d: alloc_queue.entries %d, alloc_openings %d\n",
1870 sim->sim_name, sim->unit_number,
1871 sim->devq->alloc_queue.entries, sim->devq->alloc_openings);
1872 printf("%s%d: qfrozen_cnt:", sim->sim_name, sim->unit_number);
1873 for (i = 0; i < CAM_RL_VALUES; i++) {
1874 printf("%s%u", (i != 0) ? ":" : "",
1875 sim->devq->alloc_queue.qfrozen_cnt[i]);
1876 }
1877 printf("\n");
1878}
1879
1880/*
1881 * Assumes that the SIM lock is held.
1882 */
1883static void
1884ctlfe_dump_queue(struct ctlfe_lun_softc *softc)
1885{
1886 struct ccb_hdr *hdr;
1887 struct cam_periph *periph;
1888 int num_items;
1889
1890 periph = softc->periph;
1891 num_items = 0;
1892
1893 TAILQ_FOREACH(hdr, &softc->work_queue, periph_links.tqe) {
1894 union ctl_io *io;
1895
1896 io = hdr->io_ptr;
1897
1898 num_items++;
1899
1900 /*
1901 * This can happen when we get an ATIO but can't allocate
1902 * a ctl_io. See the XPT_ACCEPT_TARGET_IO case in ctlfedone().
1903 */
1904 if (io == NULL) {
1905 struct ccb_scsiio *csio;
1906
1907 csio = (struct ccb_scsiio *)hdr;
1908
1909 xpt_print(periph->path, "CCB %#x ctl_io allocation "
1910 "failed\n", csio->tag_id);
1911 continue;
1912 }
1913
1914 /*
1915 * Only regular SCSI I/O is put on the work
1916 * queue, so we can print sense here. There may be no
1917 * sense if it's no the queue for a DMA, but this serves to
1918 * print out the CCB as well.
1919 *
1920 * XXX KDM switch this over to scsi_sense_print() when
1921 * CTL is merged in with CAM.
1922 */
1923 ctl_io_error_print(io, NULL);
1924
1925 /*
1926 * We're sending status back to the
1927 * initiator, so we're on the queue waiting
1928 * for a CTIO to do that.
1929 */
1930 if ((io->io_hdr.status & CTL_STATUS_MASK) != CTL_STATUS_NONE)
1931 continue;
1932
1933 /*
1934 * Otherwise, we're on the queue waiting to
1935 * do a data transfer.
1936 */
1937 xpt_print(periph->path, "Total %u, Current %u, Resid %u\n",
1938 io->scsiio.kern_total_len, io->scsiio.kern_data_len,
1939 io->scsiio.kern_data_resid);
1940 }
1941
1942 xpt_print(periph->path, "%d requests total waiting for CCBs\n",
1943 num_items);
1944 xpt_print(periph->path, "%ju CCBs oustanding (%ju allocated, %ju "
1945 "freed)\n", (uintmax_t)(softc->ccbs_alloced -
1946 softc->ccbs_freed), (uintmax_t)softc->ccbs_alloced,
1947 (uintmax_t)softc->ccbs_freed);
1948 xpt_print(periph->path, "%ju CTIOs outstanding (%ju sent, %ju "
1949 "returned\n", (uintmax_t)(softc->ctios_sent -
1950 softc->ctios_returned), softc->ctios_sent,
1951 softc->ctios_returned);
1952}
1953
1954/*
1955 * This function is called when we fail to get a CCB for a DMA or status return
1956 * to the initiator within the specified time period.
1957 *
1958 * The callout code should insure that we hold the sim mutex here.
1959 */
1960static void
1961ctlfe_dma_timeout(void *arg)
1962{
1963 struct ctlfe_lun_softc *softc;
1964 struct cam_periph *periph;
1965 struct cam_sim *sim;
1966 int num_queued;
1967
1968 softc = (struct ctlfe_lun_softc *)arg;
1969 periph = softc->periph;
1970 sim = xpt_path_sim(periph->path);
1971 num_queued = 0;
1972
1973 /*
1974 * Nothing to do...
1975 */
1976 if (TAILQ_FIRST(&softc->work_queue) == NULL) {
1977 xpt_print(periph->path, "TIMEOUT triggered after %d "
1978 "seconds, but nothing on work queue??\n",
1979 CTLFE_DMA_TIMEOUT);
1980 return;
1981 }
1982
1983 xpt_print(periph->path, "TIMEOUT (%d seconds) waiting for DMA to "
1984 "start\n", CTLFE_DMA_TIMEOUT);
1985
1986 ctlfe_dump_queue(softc);
1987
1988 ctlfe_dump_sim(sim);
1989
1990 xpt_print(periph->path, "calling xpt_schedule() to attempt to "
1991 "unstick our queue\n");
1992
1993 xpt_schedule(periph, /*priority*/ 1);
1994
1995 xpt_print(periph->path, "xpt_schedule() call complete\n");
1996}
1997
1998/*
1999 * Datamove/done routine called by CTL. Put ourselves on the queue to
2000 * receive a CCB from CAM so we can queue the continue I/O request down
2001 * to the adapter.
2002 */
2003static void
2004ctlfe_datamove_done(union ctl_io *io)
2005{
2006 union ccb *ccb;
2007 struct cam_sim *sim;
2008 struct cam_periph *periph;
2009 struct ctlfe_lun_softc *softc;
2010
2011 ccb = io->io_hdr.ctl_private[CTL_PRIV_FRONTEND].ptr;
2012
2013 sim = xpt_path_sim(ccb->ccb_h.path);
2014
2015 mtx_lock(sim->mtx);
2016
2017 periph = xpt_path_periph(ccb->ccb_h.path);
2018
2019 softc = (struct ctlfe_lun_softc *)periph->softc;
2020
2021 if (io->io_hdr.io_type == CTL_IO_TASK) {
2022 /*
2023 * Task management commands don't require any further
2024 * communication back to the adapter. Requeue the CCB
2025 * to the adapter, and free the CTL I/O.
2026 */
2027 xpt_print(ccb->ccb_h.path, "%s: returning task I/O "
2028 "tag %#x seq %#x\n", __func__,
2029 ccb->cin1.tag_id, ccb->cin1.seq_id);
2030 /*
2031 * Send the notify acknowledge down to the SIM, to let it
2032 * know we processed the task management command.
2033 */
2034 ccb->ccb_h.status = CAM_REQ_INPROG;
2035 ccb->ccb_h.func_code = XPT_NOTIFY_ACKNOWLEDGE;
2036 xpt_action(ccb);
2037 ctl_free_io(io);
2038 } else {
2039 if ((io->io_hdr.status & CTL_STATUS_MASK) != CTL_STATUS_NONE)
2040 io->io_hdr.flags |= CTL_FLAG_STATUS_QUEUED;
2041 else
2042 io->io_hdr.flags |= CTL_FLAG_DMA_QUEUED;
2043
2044 TAILQ_INSERT_TAIL(&softc->work_queue, &ccb->ccb_h,
2045 periph_links.tqe);
2046
2047 /*
2048 * Reset the timeout for our latest active DMA.
2049 */
2050 callout_reset(&softc->dma_callout,
2051 CTLFE_DMA_TIMEOUT * hz,
2052 ctlfe_dma_timeout, softc);
2053 /*
2054 * Ask for the CAM transport layer to send us a CCB to do
2055 * the DMA or send status, unless ctlfe_dma_enabled is set
2056 * to 0.
2057 */
2058 if (ctlfe_dma_enabled != 0)
2059 xpt_schedule(periph, /*priority*/ 1);
2060 }
2061
2062 mtx_unlock(sim->mtx);
2063}
2064
2065static void
2066ctlfe_dump(void)
2067{
2068 struct ctlfe_softc *bus_softc;
2069
2070 STAILQ_FOREACH(bus_softc, &ctlfe_softc_list, links) {
2071 struct ctlfe_lun_softc *lun_softc;
2072
2073 ctlfe_dump_sim(bus_softc->sim);
2074
2075 STAILQ_FOREACH(lun_softc, &bus_softc->lun_softc_list, links) {
2076 ctlfe_dump_queue(lun_softc);
2077 }
2078 }
2079}