]> CyberLeo.Net >> Repos - FreeBSD/stable/10.git/blob - sys/cam/ctl/ctl_tpc.c
MFC r268808:
[FreeBSD/stable/10.git] / sys / cam / ctl / ctl_tpc.c
1 /*-
2  * Copyright (c) 2014 Alexander Motin <mav@FreeBSD.org>
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, immediately at the beginning of the file.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25  */
26
27 #include <sys/cdefs.h>
28 __FBSDID("$FreeBSD$");
29
30 #include <sys/param.h>
31 #include <sys/systm.h>
32 #include <sys/kernel.h>
33 #include <sys/types.h>
34 #include <sys/lock.h>
35 #include <sys/module.h>
36 #include <sys/mutex.h>
37 #include <sys/condvar.h>
38 #include <sys/malloc.h>
39 #include <sys/conf.h>
40 #include <sys/queue.h>
41 #include <sys/sysctl.h>
42 #include <machine/atomic.h>
43
44 #include <cam/cam.h>
45 #include <cam/scsi/scsi_all.h>
46 #include <cam/scsi/scsi_da.h>
47 #include <cam/ctl/ctl_io.h>
48 #include <cam/ctl/ctl.h>
49 #include <cam/ctl/ctl_frontend.h>
50 #include <cam/ctl/ctl_frontend_internal.h>
51 #include <cam/ctl/ctl_util.h>
52 #include <cam/ctl/ctl_backend.h>
53 #include <cam/ctl/ctl_ioctl.h>
54 #include <cam/ctl/ctl_ha.h>
55 #include <cam/ctl/ctl_private.h>
56 #include <cam/ctl/ctl_debug.h>
57 #include <cam/ctl/ctl_scsi_all.h>
58 #include <cam/ctl/ctl_tpc.h>
59 #include <cam/ctl/ctl_error.h>
60
61 #define TPC_MAX_CSCDS   64
62 #define TPC_MAX_SEGS    64
63 #define TPC_MAX_SEG     0
64 #define TPC_MAX_LIST    8192
65 #define TPC_MAX_INLINE  0
66 #define TPC_MAX_LISTS   255
67 #define TPC_MAX_IO_SIZE (1024 * 1024)
68
69 MALLOC_DEFINE(M_CTL_TPC, "ctltpc", "CTL TPC");
70
71 typedef enum {
72         TPC_ERR_RETRY           = 0x000,
73         TPC_ERR_FAIL            = 0x001,
74         TPC_ERR_MASK            = 0x0ff,
75         TPC_ERR_NO_DECREMENT    = 0x100
76 } tpc_error_action;
77
78 struct tpc_list;
79 TAILQ_HEAD(runl, tpc_io);
80 struct tpc_io {
81         union ctl_io            *io;
82         uint64_t                 lun;
83         struct tpc_list         *list;
84         struct runl              run;
85         TAILQ_ENTRY(tpc_io)      rlinks;
86         TAILQ_ENTRY(tpc_io)      links;
87 };
88
89 struct tpc_list {
90         uint8_t                  service_action;
91         int                      init_port;
92         uint32_t                 init_idx;
93         uint32_t                 list_id;
94         uint8_t                  flags;
95         uint8_t                 *params;
96         struct scsi_ec_cscd     *cscd;
97         struct scsi_ec_segment  *seg[TPC_MAX_SEGS];
98         uint8_t                 *inl;
99         int                      ncscd;
100         int                      nseg;
101         int                      leninl;
102         int                      curseg;
103         off_t                    curbytes;
104         int                      curops;
105         int                      stage;
106         uint8_t                 *buf;
107         int                      segbytes;
108         int                      tbdio;
109         int                      error;
110         int                      abort;
111         int                      completed;
112         TAILQ_HEAD(, tpc_io)     allio;
113         struct scsi_sense_data   sense_data;
114         uint8_t                  sense_len;
115         uint8_t                  scsi_status;
116         struct ctl_scsiio       *ctsio;
117         struct ctl_lun          *lun;
118         TAILQ_ENTRY(tpc_list)    links;
119 };
120
121 void
122 ctl_tpc_init(struct ctl_lun *lun)
123 {
124
125         TAILQ_INIT(&lun->tpc_lists);
126 }
127
128 void
129 ctl_tpc_shutdown(struct ctl_lun *lun)
130 {
131         struct tpc_list *list;
132
133         while ((list = TAILQ_FIRST(&lun->tpc_lists)) != NULL) {
134                 TAILQ_REMOVE(&lun->tpc_lists, list, links);
135                 KASSERT(list->completed,
136                     ("Not completed TPC (%p) on shutdown", list));
137                 free(list, M_CTL);
138         }
139 }
140
141 int
142 ctl_inquiry_evpd_tpc(struct ctl_scsiio *ctsio, int alloc_len)
143 {
144         struct scsi_vpd_tpc *tpc_ptr;
145         struct scsi_vpd_tpc_descriptor *d_ptr;
146         struct scsi_vpd_tpc_descriptor_sc *sc_ptr;
147         struct scsi_vpd_tpc_descriptor_sc_descr *scd_ptr;
148         struct scsi_vpd_tpc_descriptor_pd *pd_ptr;
149         struct scsi_vpd_tpc_descriptor_sd *sd_ptr;
150         struct scsi_vpd_tpc_descriptor_sdid *sdid_ptr;
151         struct scsi_vpd_tpc_descriptor_gco *gco_ptr;
152         struct ctl_lun *lun;
153         int data_len;
154
155         lun = (struct ctl_lun *)ctsio->io_hdr.ctl_private[CTL_PRIV_LUN].ptr;
156
157         data_len = sizeof(struct scsi_vpd_tpc) +
158             roundup2(sizeof(struct scsi_vpd_tpc_descriptor_sc) +
159              2 * sizeof(struct scsi_vpd_tpc_descriptor_sc_descr) + 7, 4) +
160             sizeof(struct scsi_vpd_tpc_descriptor_pd) +
161             roundup2(sizeof(struct scsi_vpd_tpc_descriptor_sd) + 4, 4) +
162             roundup2(sizeof(struct scsi_vpd_tpc_descriptor_sdid) + 2, 4) +
163             sizeof(struct scsi_vpd_tpc_descriptor_gco);
164
165         ctsio->kern_data_ptr = malloc(data_len, M_CTL, M_WAITOK | M_ZERO);
166         tpc_ptr = (struct scsi_vpd_tpc *)ctsio->kern_data_ptr;
167         ctsio->kern_sg_entries = 0;
168
169         if (data_len < alloc_len) {
170                 ctsio->residual = alloc_len - data_len;
171                 ctsio->kern_data_len = data_len;
172                 ctsio->kern_total_len = data_len;
173         } else {
174                 ctsio->residual = 0;
175                 ctsio->kern_data_len = alloc_len;
176                 ctsio->kern_total_len = alloc_len;
177         }
178         ctsio->kern_data_resid = 0;
179         ctsio->kern_rel_offset = 0;
180         ctsio->kern_sg_entries = 0;
181
182         /*
183          * The control device is always connected.  The disk device, on the
184          * other hand, may not be online all the time.
185          */
186         if (lun != NULL)
187                 tpc_ptr->device = (SID_QUAL_LU_CONNECTED << 5) |
188                                      lun->be_lun->lun_type;
189         else
190                 tpc_ptr->device = (SID_QUAL_LU_OFFLINE << 5) | T_DIRECT;
191         tpc_ptr->page_code = SVPD_SCSI_TPC;
192         scsi_ulto2b(data_len - 4, tpc_ptr->page_length);
193
194         /* Supported commands */
195         d_ptr = (struct scsi_vpd_tpc_descriptor *)&tpc_ptr->descr[0];
196         sc_ptr = (struct scsi_vpd_tpc_descriptor_sc *)d_ptr;
197         scsi_ulto2b(SVPD_TPC_SC, sc_ptr->desc_type);
198         sc_ptr->list_length = 2 * sizeof(*scd_ptr) + 7;
199         scsi_ulto2b(roundup2(1 + sc_ptr->list_length, 4), sc_ptr->desc_length);
200         scd_ptr = &sc_ptr->descr[0];
201         scd_ptr->opcode = EXTENDED_COPY;
202         scd_ptr->sa_length = 3;
203         scd_ptr->supported_service_actions[0] = EC_EC_LID1;
204         scd_ptr->supported_service_actions[1] = EC_EC_LID4;
205         scd_ptr->supported_service_actions[2] = EC_COA;
206         scd_ptr = (struct scsi_vpd_tpc_descriptor_sc_descr *)
207             &scd_ptr->supported_service_actions[scd_ptr->sa_length];
208         scd_ptr->opcode = RECEIVE_COPY_STATUS;
209         scd_ptr->sa_length = 4;
210         scd_ptr->supported_service_actions[0] = RCS_RCS_LID1;
211         scd_ptr->supported_service_actions[1] = RCS_RCFD;
212         scd_ptr->supported_service_actions[2] = RCS_RCS_LID4;
213         scd_ptr->supported_service_actions[3] = RCS_RCOP;
214
215         /* Parameter data. */
216         d_ptr = (struct scsi_vpd_tpc_descriptor *)
217             (&d_ptr->parameters[0] + scsi_2btoul(d_ptr->desc_length));
218         pd_ptr = (struct scsi_vpd_tpc_descriptor_pd *)d_ptr;
219         scsi_ulto2b(SVPD_TPC_PD, pd_ptr->desc_type);
220         scsi_ulto2b(sizeof(*pd_ptr) - 4, pd_ptr->desc_length);
221         scsi_ulto2b(TPC_MAX_CSCDS, pd_ptr->maximum_cscd_descriptor_count);
222         scsi_ulto2b(TPC_MAX_SEGS, pd_ptr->maximum_segment_descriptor_count);
223         scsi_ulto4b(TPC_MAX_LIST, pd_ptr->maximum_descriptor_list_length);
224         scsi_ulto4b(TPC_MAX_INLINE, pd_ptr->maximum_inline_data_length);
225
226         /* Supported Descriptors */
227         d_ptr = (struct scsi_vpd_tpc_descriptor *)
228             (&d_ptr->parameters[0] + scsi_2btoul(d_ptr->desc_length));
229         sd_ptr = (struct scsi_vpd_tpc_descriptor_sd *)d_ptr;
230         scsi_ulto2b(SVPD_TPC_SD, sd_ptr->desc_type);
231         scsi_ulto2b(roundup2(sizeof(*sd_ptr) - 4 + 4, 4), sd_ptr->desc_length);
232         sd_ptr->list_length = 4;
233         sd_ptr->supported_descriptor_codes[0] = EC_SEG_B2B;
234         sd_ptr->supported_descriptor_codes[1] = EC_SEG_VERIFY;
235         sd_ptr->supported_descriptor_codes[2] = EC_SEG_REGISTER_KEY;
236         sd_ptr->supported_descriptor_codes[3] = EC_CSCD_ID;
237
238         /* Supported CSCD Descriptor IDs */
239         d_ptr = (struct scsi_vpd_tpc_descriptor *)
240             (&d_ptr->parameters[0] + scsi_2btoul(d_ptr->desc_length));
241         sdid_ptr = (struct scsi_vpd_tpc_descriptor_sdid *)d_ptr;
242         scsi_ulto2b(SVPD_TPC_SDID, sdid_ptr->desc_type);
243         scsi_ulto2b(roundup2(sizeof(*sdid_ptr) - 4 + 2, 4), sdid_ptr->desc_length);
244         scsi_ulto2b(2, sdid_ptr->list_length);
245         scsi_ulto2b(0xffff, &sdid_ptr->supported_descriptor_ids[0]);
246
247         /* General Copy Operations */
248         d_ptr = (struct scsi_vpd_tpc_descriptor *)
249             (&d_ptr->parameters[0] + scsi_2btoul(d_ptr->desc_length));
250         gco_ptr = (struct scsi_vpd_tpc_descriptor_gco *)d_ptr;
251         scsi_ulto2b(SVPD_TPC_GCO, gco_ptr->desc_type);
252         scsi_ulto2b(sizeof(*gco_ptr) - 4, gco_ptr->desc_length);
253         scsi_ulto4b(TPC_MAX_LISTS, gco_ptr->total_concurrent_copies);
254         scsi_ulto4b(TPC_MAX_LISTS, gco_ptr->maximum_identified_concurrent_copies);
255         scsi_ulto4b(TPC_MAX_SEG, gco_ptr->maximum_segment_length);
256         gco_ptr->data_segment_granularity = 0;
257         gco_ptr->inline_data_granularity = 0;
258
259         ctsio->scsi_status = SCSI_STATUS_OK;
260         ctsio->io_hdr.flags |= CTL_FLAG_ALLOCATED;
261         ctsio->be_move_done = ctl_config_move_done;
262         ctl_datamove((union ctl_io *)ctsio);
263
264         return (CTL_RETVAL_COMPLETE);
265 }
266
267 int
268 ctl_receive_copy_operating_parameters(struct ctl_scsiio *ctsio)
269 {
270         struct ctl_lun *lun;
271         struct scsi_receive_copy_operating_parameters *cdb;
272         struct scsi_receive_copy_operating_parameters_data *data;
273         int retval;
274         int alloc_len, total_len;
275
276         CTL_DEBUG_PRINT(("ctl_report_supported_tmf\n"));
277
278         cdb = (struct scsi_receive_copy_operating_parameters *)ctsio->cdb;
279         lun = (struct ctl_lun *)ctsio->io_hdr.ctl_private[CTL_PRIV_LUN].ptr;
280
281         retval = CTL_RETVAL_COMPLETE;
282
283         total_len = sizeof(*data) + 4;
284         alloc_len = scsi_4btoul(cdb->length);
285
286         ctsio->kern_data_ptr = malloc(total_len, M_CTL, M_WAITOK | M_ZERO);
287
288         ctsio->kern_sg_entries = 0;
289
290         if (total_len < alloc_len) {
291                 ctsio->residual = alloc_len - total_len;
292                 ctsio->kern_data_len = total_len;
293                 ctsio->kern_total_len = total_len;
294         } else {
295                 ctsio->residual = 0;
296                 ctsio->kern_data_len = alloc_len;
297                 ctsio->kern_total_len = alloc_len;
298         }
299         ctsio->kern_data_resid = 0;
300         ctsio->kern_rel_offset = 0;
301
302         data = (struct scsi_receive_copy_operating_parameters_data *)ctsio->kern_data_ptr;
303         scsi_ulto4b(sizeof(*data) - 4 + 4, data->length);
304         data->snlid = RCOP_SNLID;
305         scsi_ulto2b(TPC_MAX_CSCDS, data->maximum_cscd_descriptor_count);
306         scsi_ulto2b(TPC_MAX_SEGS, data->maximum_segment_descriptor_count);
307         scsi_ulto4b(TPC_MAX_LIST, data->maximum_descriptor_list_length);
308         scsi_ulto4b(TPC_MAX_SEG, data->maximum_segment_length);
309         scsi_ulto4b(TPC_MAX_INLINE, data->maximum_inline_data_length);
310         scsi_ulto4b(0, data->held_data_limit);
311         scsi_ulto4b(0, data->maximum_stream_device_transfer_size);
312         scsi_ulto2b(TPC_MAX_LISTS, data->total_concurrent_copies);
313         data->maximum_concurrent_copies = TPC_MAX_LISTS;
314         data->data_segment_granularity = 0;
315         data->inline_data_granularity = 0;
316         data->held_data_granularity = 0;
317         data->implemented_descriptor_list_length = 4;
318         data->list_of_implemented_descriptor_type_codes[0] = EC_SEG_B2B;
319         data->list_of_implemented_descriptor_type_codes[1] = EC_SEG_VERIFY;
320         data->list_of_implemented_descriptor_type_codes[2] = EC_SEG_REGISTER_KEY;
321         data->list_of_implemented_descriptor_type_codes[3] = EC_CSCD_ID;
322
323         ctsio->io_hdr.flags |= CTL_FLAG_ALLOCATED;
324         ctsio->be_move_done = ctl_config_move_done;
325
326         ctl_datamove((union ctl_io *)ctsio);
327         return (retval);
328 }
329
330 int
331 ctl_receive_copy_status_lid1(struct ctl_scsiio *ctsio)
332 {
333         struct ctl_lun *lun;
334         struct scsi_receive_copy_status_lid1 *cdb;
335         struct scsi_receive_copy_status_lid1_data *data;
336         struct tpc_list *list;
337         struct tpc_list list_copy;
338         int retval;
339         int alloc_len, total_len;
340         uint32_t list_id;
341
342         CTL_DEBUG_PRINT(("ctl_receive_copy_status_lid1\n"));
343
344         cdb = (struct scsi_receive_copy_status_lid1 *)ctsio->cdb;
345         lun = (struct ctl_lun *)ctsio->io_hdr.ctl_private[CTL_PRIV_LUN].ptr;
346
347         retval = CTL_RETVAL_COMPLETE;
348
349         list_id = cdb->list_identifier;
350         mtx_lock(&lun->lun_lock);
351         TAILQ_FOREACH(list, &lun->tpc_lists, links) {
352                 if ((list->flags & EC_LIST_ID_USAGE_MASK) !=
353                      EC_LIST_ID_USAGE_NONE && list->list_id == list_id)
354                         break;
355         }
356         if (list == NULL) {
357                 mtx_unlock(&lun->lun_lock);
358                 ctl_set_invalid_field(ctsio, /*sks_valid*/ 1,
359                     /*command*/ 1, /*field*/ 2, /*bit_valid*/ 0,
360                     /*bit*/ 0);
361                 ctl_done((union ctl_io *)ctsio);
362                 return (retval);
363         }
364         list_copy = *list;
365         if (list->completed) {
366                 TAILQ_REMOVE(&lun->tpc_lists, list, links);
367                 free(list, M_CTL);
368         }
369         mtx_unlock(&lun->lun_lock);
370
371         total_len = sizeof(*data);
372         alloc_len = scsi_4btoul(cdb->length);
373
374         ctsio->kern_data_ptr = malloc(total_len, M_CTL, M_WAITOK | M_ZERO);
375
376         ctsio->kern_sg_entries = 0;
377
378         if (total_len < alloc_len) {
379                 ctsio->residual = alloc_len - total_len;
380                 ctsio->kern_data_len = total_len;
381                 ctsio->kern_total_len = total_len;
382         } else {
383                 ctsio->residual = 0;
384                 ctsio->kern_data_len = alloc_len;
385                 ctsio->kern_total_len = alloc_len;
386         }
387         ctsio->kern_data_resid = 0;
388         ctsio->kern_rel_offset = 0;
389
390         data = (struct scsi_receive_copy_status_lid1_data *)ctsio->kern_data_ptr;
391         scsi_ulto4b(sizeof(*data) - 4, data->available_data);
392         if (list_copy.completed) {
393                 if (list_copy.error || list_copy.abort)
394                         data->copy_command_status = RCS_CCS_ERROR;
395                 else
396                         data->copy_command_status = RCS_CCS_COMPLETED;
397         } else
398                 data->copy_command_status = RCS_CCS_INPROG;
399         scsi_ulto2b(list_copy.curseg, data->segments_processed);
400         if (list_copy.curbytes <= UINT32_MAX) {
401                 data->transfer_count_units = RCS_TC_BYTES;
402                 scsi_ulto4b(list_copy.curbytes, data->transfer_count);
403         } else {
404                 data->transfer_count_units = RCS_TC_MBYTES;
405                 scsi_ulto4b(list_copy.curbytes >> 20, data->transfer_count);
406         }
407
408         ctsio->io_hdr.flags |= CTL_FLAG_ALLOCATED;
409         ctsio->be_move_done = ctl_config_move_done;
410
411         ctl_datamove((union ctl_io *)ctsio);
412         return (retval);
413 }
414
415 int
416 ctl_receive_copy_failure_details(struct ctl_scsiio *ctsio)
417 {
418         struct ctl_lun *lun;
419         struct scsi_receive_copy_failure_details *cdb;
420         struct scsi_receive_copy_failure_details_data *data;
421         struct tpc_list *list;
422         struct tpc_list list_copy;
423         int retval;
424         int alloc_len, total_len;
425         uint32_t list_id;
426
427         CTL_DEBUG_PRINT(("ctl_receive_copy_failure_details\n"));
428
429         cdb = (struct scsi_receive_copy_failure_details *)ctsio->cdb;
430         lun = (struct ctl_lun *)ctsio->io_hdr.ctl_private[CTL_PRIV_LUN].ptr;
431
432         retval = CTL_RETVAL_COMPLETE;
433
434         list_id = cdb->list_identifier;
435         mtx_lock(&lun->lun_lock);
436         TAILQ_FOREACH(list, &lun->tpc_lists, links) {
437                 if (list->completed && (list->flags & EC_LIST_ID_USAGE_MASK) !=
438                      EC_LIST_ID_USAGE_NONE && list->list_id == list_id)
439                         break;
440         }
441         if (list == NULL) {
442                 mtx_unlock(&lun->lun_lock);
443                 ctl_set_invalid_field(ctsio, /*sks_valid*/ 1,
444                     /*command*/ 1, /*field*/ 2, /*bit_valid*/ 0,
445                     /*bit*/ 0);
446                 ctl_done((union ctl_io *)ctsio);
447                 return (retval);
448         }
449         list_copy = *list;
450         TAILQ_REMOVE(&lun->tpc_lists, list, links);
451         free(list, M_CTL);
452         mtx_unlock(&lun->lun_lock);
453
454         total_len = sizeof(*data) + list_copy.sense_len;
455         alloc_len = scsi_4btoul(cdb->length);
456
457         ctsio->kern_data_ptr = malloc(total_len, M_CTL, M_WAITOK | M_ZERO);
458
459         ctsio->kern_sg_entries = 0;
460
461         if (total_len < alloc_len) {
462                 ctsio->residual = alloc_len - total_len;
463                 ctsio->kern_data_len = total_len;
464                 ctsio->kern_total_len = total_len;
465         } else {
466                 ctsio->residual = 0;
467                 ctsio->kern_data_len = alloc_len;
468                 ctsio->kern_total_len = alloc_len;
469         }
470         ctsio->kern_data_resid = 0;
471         ctsio->kern_rel_offset = 0;
472
473         data = (struct scsi_receive_copy_failure_details_data *)ctsio->kern_data_ptr;
474         if (list_copy.completed && (list_copy.error || list_copy.abort)) {
475                 scsi_ulto4b(sizeof(*data) - 4, data->available_data);
476                 data->copy_command_status = RCS_CCS_ERROR;
477         } else
478                 scsi_ulto4b(0, data->available_data);
479         scsi_ulto2b(list_copy.sense_len, data->sense_data_length);
480         memcpy(data->sense_data, &list_copy.sense_data, list_copy.sense_len);
481
482         ctsio->io_hdr.flags |= CTL_FLAG_ALLOCATED;
483         ctsio->be_move_done = ctl_config_move_done;
484
485         ctl_datamove((union ctl_io *)ctsio);
486         return (retval);
487 }
488
489 int
490 ctl_receive_copy_status_lid4(struct ctl_scsiio *ctsio)
491 {
492         struct ctl_lun *lun;
493         struct scsi_receive_copy_status_lid4 *cdb;
494         struct scsi_receive_copy_status_lid4_data *data;
495         struct tpc_list *list;
496         struct tpc_list list_copy;
497         int retval;
498         int alloc_len, total_len;
499         uint32_t list_id;
500
501         CTL_DEBUG_PRINT(("ctl_receive_copy_status_lid4\n"));
502
503         cdb = (struct scsi_receive_copy_status_lid4 *)ctsio->cdb;
504         lun = (struct ctl_lun *)ctsio->io_hdr.ctl_private[CTL_PRIV_LUN].ptr;
505
506         retval = CTL_RETVAL_COMPLETE;
507
508         list_id = scsi_4btoul(cdb->list_identifier);
509         mtx_lock(&lun->lun_lock);
510         TAILQ_FOREACH(list, &lun->tpc_lists, links) {
511                 if ((list->flags & EC_LIST_ID_USAGE_MASK) !=
512                      EC_LIST_ID_USAGE_NONE && list->list_id == list_id)
513                         break;
514         }
515         if (list == NULL) {
516                 mtx_unlock(&lun->lun_lock);
517                 ctl_set_invalid_field(ctsio, /*sks_valid*/ 1,
518                     /*command*/ 1, /*field*/ 2, /*bit_valid*/ 0,
519                     /*bit*/ 0);
520                 ctl_done((union ctl_io *)ctsio);
521                 return (retval);
522         }
523         list_copy = *list;
524         if (list->completed) {
525                 TAILQ_REMOVE(&lun->tpc_lists, list, links);
526                 free(list, M_CTL);
527         }
528         mtx_unlock(&lun->lun_lock);
529
530         total_len = sizeof(*data) + list_copy.sense_len;
531         alloc_len = scsi_4btoul(cdb->length);
532
533         ctsio->kern_data_ptr = malloc(total_len, M_CTL, M_WAITOK | M_ZERO);
534
535         ctsio->kern_sg_entries = 0;
536
537         if (total_len < alloc_len) {
538                 ctsio->residual = alloc_len - total_len;
539                 ctsio->kern_data_len = total_len;
540                 ctsio->kern_total_len = total_len;
541         } else {
542                 ctsio->residual = 0;
543                 ctsio->kern_data_len = alloc_len;
544                 ctsio->kern_total_len = alloc_len;
545         }
546         ctsio->kern_data_resid = 0;
547         ctsio->kern_rel_offset = 0;
548
549         data = (struct scsi_receive_copy_status_lid4_data *)ctsio->kern_data_ptr;
550         scsi_ulto4b(sizeof(*data) - 4, data->available_data);
551         data->response_to_service_action = list_copy.service_action;
552         if (list_copy.completed) {
553                 if (list_copy.error)
554                         data->copy_command_status = RCS_CCS_ERROR;
555                 else if (list_copy.abort)
556                         data->copy_command_status = RCS_CCS_ABORTED;
557                 else
558                         data->copy_command_status = RCS_CCS_COMPLETED;
559         } else
560                 data->copy_command_status = RCS_CCS_INPROG_FG;
561         scsi_ulto2b(list_copy.curops, data->operation_counter);
562         scsi_ulto4b(UINT32_MAX, data->estimated_status_update_delay);
563         if (list_copy.curbytes <= UINT32_MAX) {
564                 data->transfer_count_units = RCS_TC_BYTES;
565                 scsi_ulto4b(list_copy.curbytes, data->transfer_count);
566         } else {
567                 data->transfer_count_units = RCS_TC_MBYTES;
568                 scsi_ulto4b(list_copy.curbytes >> 20, data->transfer_count);
569         }
570         scsi_ulto2b(list_copy.curseg, data->segments_processed);
571         data->sense_data_length = list_copy.sense_len;
572         memcpy(data->sense_data, &list_copy.sense_data, list_copy.sense_len);
573
574         ctsio->io_hdr.flags |= CTL_FLAG_ALLOCATED;
575         ctsio->be_move_done = ctl_config_move_done;
576
577         ctl_datamove((union ctl_io *)ctsio);
578         return (retval);
579 }
580
581 int
582 ctl_copy_operation_abort(struct ctl_scsiio *ctsio)
583 {
584         struct ctl_lun *lun;
585         struct scsi_copy_operation_abort *cdb;
586         struct tpc_list *list;
587         int retval;
588         uint32_t list_id;
589
590         CTL_DEBUG_PRINT(("ctl_copy_operation_abort\n"));
591
592         cdb = (struct scsi_copy_operation_abort *)ctsio->cdb;
593         lun = (struct ctl_lun *)ctsio->io_hdr.ctl_private[CTL_PRIV_LUN].ptr;
594
595         retval = CTL_RETVAL_COMPLETE;
596
597         list_id = scsi_4btoul(cdb->list_identifier);
598         mtx_lock(&lun->lun_lock);
599         TAILQ_FOREACH(list, &lun->tpc_lists, links) {
600                 if ((list->flags & EC_LIST_ID_USAGE_MASK) !=
601                      EC_LIST_ID_USAGE_NONE && list->list_id == list_id)
602                         break;
603         }
604         if (list == NULL) {
605                 mtx_unlock(&lun->lun_lock);
606                 ctl_set_invalid_field(ctsio, /*sks_valid*/ 1,
607                     /*command*/ 1, /*field*/ 2, /*bit_valid*/ 0,
608                     /*bit*/ 0);
609                 ctl_done((union ctl_io *)ctsio);
610                 return (retval);
611         }
612         list->abort = 1;
613         mtx_unlock(&lun->lun_lock);
614
615         ctl_set_success(ctsio);
616         ctl_done((union ctl_io *)ctsio);
617         return (retval);
618 }
619
620 static uint64_t
621 tpc_resolve(struct tpc_list *list, uint16_t idx, uint32_t *ss)
622 {
623
624         if (idx == 0xffff) {
625                 if (ss && list->lun->be_lun)
626                         *ss = list->lun->be_lun->blocksize;
627                 return (list->lun->lun);
628         }
629         if (idx >= list->ncscd)
630                 return (UINT64_MAX);
631         return (tpcl_resolve(list->init_port, &list->cscd[idx], ss));
632 }
633
634 static int
635 tpc_process_b2b(struct tpc_list *list)
636 {
637         struct scsi_ec_segment_b2b *seg;
638         struct scsi_ec_cscd_dtsp *sdstp, *ddstp;
639         struct tpc_io *tior, *tiow;
640         struct runl run, *prun;
641         uint64_t sl, dl;
642         off_t srclba, dstlba, numbytes, donebytes, roundbytes;
643         int numlba;
644         uint32_t srcblock, dstblock;
645
646         if (list->stage == 1) {
647 complete:
648                 while ((tior = TAILQ_FIRST(&list->allio)) != NULL) {
649                         TAILQ_REMOVE(&list->allio, tior, links);
650                         ctl_free_io(tior->io);
651                         free(tior, M_CTL);
652                 }
653                 free(list->buf, M_CTL);
654                 if (list->abort) {
655                         ctl_set_task_aborted(list->ctsio);
656                         return (CTL_RETVAL_ERROR);
657                 } else if (list->error) {
658                         ctl_set_sense(list->ctsio, /*current_error*/ 1,
659                             /*sense_key*/ SSD_KEY_COPY_ABORTED,
660                             /*asc*/ 0x0d, /*ascq*/ 0x01, SSD_ELEM_NONE);
661                         return (CTL_RETVAL_ERROR);
662                 } else {
663                         list->curbytes += list->segbytes;
664                         return (CTL_RETVAL_COMPLETE);
665                 }
666         }
667
668         TAILQ_INIT(&list->allio);
669         seg = (struct scsi_ec_segment_b2b *)list->seg[list->curseg];
670         sl = tpc_resolve(list, scsi_2btoul(seg->src_cscd), &srcblock);
671         dl = tpc_resolve(list, scsi_2btoul(seg->dst_cscd), &dstblock);
672         if (sl >= CTL_MAX_LUNS || dl >= CTL_MAX_LUNS) {
673                 ctl_set_sense(list->ctsio, /*current_error*/ 1,
674                     /*sense_key*/ SSD_KEY_COPY_ABORTED,
675                     /*asc*/ 0x08, /*ascq*/ 0x04, SSD_ELEM_NONE);
676                 return (CTL_RETVAL_ERROR);
677         }
678         sdstp = &list->cscd[scsi_2btoul(seg->src_cscd)].dtsp;
679         if (scsi_3btoul(sdstp->block_length) != 0)
680                 srcblock = scsi_3btoul(sdstp->block_length);
681         ddstp = &list->cscd[scsi_2btoul(seg->dst_cscd)].dtsp;
682         if (scsi_3btoul(ddstp->block_length) != 0)
683                 dstblock = scsi_3btoul(ddstp->block_length);
684         numlba = scsi_2btoul(seg->number_of_blocks);
685         if (seg->flags & EC_SEG_DC)
686                 numbytes = (off_t)numlba * dstblock;
687         else
688                 numbytes = (off_t)numlba * srcblock;
689         srclba = scsi_8btou64(seg->src_lba);
690         dstlba = scsi_8btou64(seg->dst_lba);
691
692 //      printf("Copy %ju bytes from %ju @ %ju to %ju @ %ju\n",
693 //          (uintmax_t)numbytes, sl, scsi_8btou64(seg->src_lba),
694 //          dl, scsi_8btou64(seg->dst_lba));
695
696         if (numbytes == 0)
697                 return (CTL_RETVAL_COMPLETE);
698
699         if (numbytes % srcblock != 0 || numbytes % dstblock != 0) {
700                 ctl_set_sense(list->ctsio, /*current_error*/ 1,
701                     /*sense_key*/ SSD_KEY_COPY_ABORTED,
702                     /*asc*/ 0x26, /*ascq*/ 0x0A, SSD_ELEM_NONE);
703                 return (CTL_RETVAL_ERROR);
704         }
705
706         list->buf = malloc(numbytes, M_CTL, M_WAITOK);
707         list->segbytes = numbytes;
708         donebytes = 0;
709         TAILQ_INIT(&run);
710         prun = &run;
711         list->tbdio = 1;
712         while (donebytes < numbytes) {
713                 roundbytes = MIN(numbytes - donebytes, TPC_MAX_IO_SIZE);
714
715                 tior = malloc(sizeof(*tior), M_CTL, M_WAITOK | M_ZERO);
716                 TAILQ_INIT(&tior->run);
717                 tior->list = list;
718                 TAILQ_INSERT_TAIL(&list->allio, tior, links);
719                 tior->io = tpcl_alloc_io();
720                 if (tior->io == NULL) {
721                         list->error = 1;
722                         goto complete;
723                 }
724                 ctl_scsi_read_write(tior->io,
725                                     /*data_ptr*/ &list->buf[donebytes],
726                                     /*data_len*/ roundbytes,
727                                     /*read_op*/ 1,
728                                     /*byte2*/ 0,
729                                     /*minimum_cdb_size*/ 0,
730                                     /*lba*/ srclba + donebytes / srcblock,
731                                     /*num_blocks*/ roundbytes / srcblock,
732                                     /*tag_type*/ CTL_TAG_SIMPLE,
733                                     /*control*/ 0);
734                 tior->io->io_hdr.retries = 3;
735                 tior->lun = sl;
736                 tior->io->io_hdr.ctl_private[CTL_PRIV_FRONTEND].ptr = tior;
737
738                 tiow = malloc(sizeof(*tior), M_CTL, M_WAITOK | M_ZERO);
739                 TAILQ_INIT(&tiow->run);
740                 tiow->list = list;
741                 TAILQ_INSERT_TAIL(&list->allio, tiow, links);
742                 tiow->io = tpcl_alloc_io();
743                 if (tiow->io == NULL) {
744                         list->error = 1;
745                         goto complete;
746                 }
747                 ctl_scsi_read_write(tiow->io,
748                                     /*data_ptr*/ &list->buf[donebytes],
749                                     /*data_len*/ roundbytes,
750                                     /*read_op*/ 0,
751                                     /*byte2*/ 0,
752                                     /*minimum_cdb_size*/ 0,
753                                     /*lba*/ dstlba + donebytes / dstblock,
754                                     /*num_blocks*/ roundbytes / dstblock,
755                                     /*tag_type*/ CTL_TAG_SIMPLE,
756                                     /*control*/ 0);
757                 tiow->io->io_hdr.retries = 3;
758                 tiow->lun = dl;
759                 tiow->io->io_hdr.ctl_private[CTL_PRIV_FRONTEND].ptr = tior;
760
761                 TAILQ_INSERT_TAIL(&tior->run, tiow, rlinks);
762                 TAILQ_INSERT_TAIL(prun, tior, rlinks);
763                 prun = &tior->run;
764                 donebytes += roundbytes;
765         }
766
767         while ((tior = TAILQ_FIRST(&run)) != NULL) {
768                 TAILQ_REMOVE(&run, tior, rlinks);
769                 if (tpcl_queue(tior->io, tior->lun) != CTL_RETVAL_COMPLETE)
770                         panic("tpcl_queue() error");
771         }
772
773         list->stage++;
774         return (CTL_RETVAL_QUEUED);
775 }
776
777 static int
778 tpc_process_verify(struct tpc_list *list)
779 {
780         struct scsi_ec_segment_verify *seg;
781         struct tpc_io *tio;
782         uint64_t sl;
783
784         if (list->stage == 1) {
785 complete:
786                 while ((tio = TAILQ_FIRST(&list->allio)) != NULL) {
787                         TAILQ_REMOVE(&list->allio, tio, links);
788                         ctl_free_io(tio->io);
789                         free(tio, M_CTL);
790                 }
791                 if (list->abort) {
792                         ctl_set_task_aborted(list->ctsio);
793                         return (CTL_RETVAL_ERROR);
794                 } else if (list->error) {
795                         ctl_set_sense(list->ctsio, /*current_error*/ 1,
796                             /*sense_key*/ SSD_KEY_COPY_ABORTED,
797                             /*asc*/ 0x0d, /*ascq*/ 0x01, SSD_ELEM_NONE);
798                         return (CTL_RETVAL_ERROR);
799                 } else
800                         return (CTL_RETVAL_COMPLETE);
801         }
802
803         TAILQ_INIT(&list->allio);
804         seg = (struct scsi_ec_segment_verify *)list->seg[list->curseg];
805         sl = tpc_resolve(list, scsi_2btoul(seg->src_cscd), NULL);
806         if (sl >= CTL_MAX_LUNS) {
807                 ctl_set_sense(list->ctsio, /*current_error*/ 1,
808                     /*sense_key*/ SSD_KEY_COPY_ABORTED,
809                     /*asc*/ 0x08, /*ascq*/ 0x04, SSD_ELEM_NONE);
810                 return (CTL_RETVAL_ERROR);
811         }
812
813 //      printf("Verify %ju\n", sl);
814
815         if ((seg->tur & 0x01) == 0)
816                 return (CTL_RETVAL_COMPLETE);
817
818         list->tbdio = 1;
819         tio = malloc(sizeof(*tio), M_CTL, M_WAITOK | M_ZERO);
820         TAILQ_INIT(&tio->run);
821         tio->list = list;
822         TAILQ_INSERT_TAIL(&list->allio, tio, links);
823         tio->io = tpcl_alloc_io();
824         if (tio->io == NULL) {
825                 list->error = 1;
826                 goto complete;
827         }
828         ctl_scsi_tur(tio->io, /*tag_type*/ CTL_TAG_SIMPLE, /*control*/ 0);
829         tio->io->io_hdr.retries = 3;
830         tio->lun = sl;
831         tio->io->io_hdr.ctl_private[CTL_PRIV_FRONTEND].ptr = tio;
832         list->stage++;
833         if (tpcl_queue(tio->io, tio->lun) != CTL_RETVAL_COMPLETE)
834                 panic("tpcl_queue() error");
835         return (CTL_RETVAL_QUEUED);
836 }
837
838 static int
839 tpc_process_register_key(struct tpc_list *list)
840 {
841         struct scsi_ec_segment_register_key *seg;
842         struct tpc_io *tio;
843         uint64_t dl;
844         int datalen;
845
846         if (list->stage == 1) {
847 complete:
848                 while ((tio = TAILQ_FIRST(&list->allio)) != NULL) {
849                         TAILQ_REMOVE(&list->allio, tio, links);
850                         ctl_free_io(tio->io);
851                         free(tio, M_CTL);
852                 }
853                 free(list->buf, M_CTL);
854                 if (list->abort) {
855                         ctl_set_task_aborted(list->ctsio);
856                         return (CTL_RETVAL_ERROR);
857                 } else if (list->error) {
858                         ctl_set_sense(list->ctsio, /*current_error*/ 1,
859                             /*sense_key*/ SSD_KEY_COPY_ABORTED,
860                             /*asc*/ 0x0d, /*ascq*/ 0x01, SSD_ELEM_NONE);
861                         return (CTL_RETVAL_ERROR);
862                 } else
863                         return (CTL_RETVAL_COMPLETE);
864         }
865
866         TAILQ_INIT(&list->allio);
867         seg = (struct scsi_ec_segment_register_key *)list->seg[list->curseg];
868         dl = tpc_resolve(list, scsi_2btoul(seg->dst_cscd), NULL);
869         if (dl >= CTL_MAX_LUNS) {
870                 ctl_set_sense(list->ctsio, /*current_error*/ 1,
871                     /*sense_key*/ SSD_KEY_COPY_ABORTED,
872                     /*asc*/ 0x08, /*ascq*/ 0x04, SSD_ELEM_NONE);
873                 return (CTL_RETVAL_ERROR);
874         }
875
876 //      printf("Register Key %ju\n", dl);
877
878         list->tbdio = 1;
879         tio = malloc(sizeof(*tio), M_CTL, M_WAITOK | M_ZERO);
880         TAILQ_INIT(&tio->run);
881         tio->list = list;
882         TAILQ_INSERT_TAIL(&list->allio, tio, links);
883         tio->io = tpcl_alloc_io();
884         if (tio->io == NULL) {
885                 list->error = 1;
886                 goto complete;
887         }
888         datalen = sizeof(struct scsi_per_res_out_parms);
889         list->buf = malloc(datalen, M_CTL, M_WAITOK);
890         ctl_scsi_persistent_res_out(tio->io,
891             list->buf, datalen, SPRO_REGISTER, -1,
892             scsi_8btou64(seg->res_key), scsi_8btou64(seg->sa_res_key),
893             /*tag_type*/ CTL_TAG_SIMPLE, /*control*/ 0);
894         tio->io->io_hdr.retries = 3;
895         tio->lun = dl;
896         tio->io->io_hdr.ctl_private[CTL_PRIV_FRONTEND].ptr = tio;
897         list->stage++;
898         if (tpcl_queue(tio->io, tio->lun) != CTL_RETVAL_COMPLETE)
899                 panic("tpcl_queue() error");
900         return (CTL_RETVAL_QUEUED);
901 }
902
903 static void
904 tpc_process(struct tpc_list *list)
905 {
906         struct ctl_lun *lun = list->lun;
907         struct scsi_ec_segment *seg;
908         struct ctl_scsiio *ctsio = list->ctsio;
909         int retval = CTL_RETVAL_COMPLETE;
910
911 //printf("ZZZ %d cscd, %d segs\n", list->ncscd, list->nseg);
912         while (list->curseg < list->nseg) {
913                 seg = list->seg[list->curseg];
914                 switch (seg->type_code) {
915                 case EC_SEG_B2B:
916                         retval = tpc_process_b2b(list);
917                         break;
918                 case EC_SEG_VERIFY:
919                         retval = tpc_process_verify(list);
920                         break;
921                 case EC_SEG_REGISTER_KEY:
922                         retval = tpc_process_register_key(list);
923                         break;
924                 default:
925                         ctl_set_sense(ctsio, /*current_error*/ 1,
926                             /*sense_key*/ SSD_KEY_COPY_ABORTED,
927                             /*asc*/ 0x26, /*ascq*/ 0x09, SSD_ELEM_NONE);
928                         goto done;
929                 }
930                 if (retval == CTL_RETVAL_QUEUED)
931                         return;
932                 if (retval == CTL_RETVAL_ERROR) {
933                         list->error = 1;
934                         goto done;
935                 }
936                 list->curseg++;
937                 list->stage = 0;
938         }
939
940         ctl_set_success(ctsio);
941
942 done:
943 //printf("ZZZ done\n");
944         mtx_lock(&lun->lun_lock);
945         if ((list->flags & EC_LIST_ID_USAGE_MASK) == EC_LIST_ID_USAGE_NONE) {
946                 TAILQ_REMOVE(&lun->tpc_lists, list, links);
947                 free(list, M_CTL);
948         } else {
949                 list->completed = 1;
950                 list->sense_data = ctsio->sense_data;
951                 list->sense_len = ctsio->sense_len;
952                 list->scsi_status = ctsio->scsi_status;
953         }
954         mtx_unlock(&lun->lun_lock);
955
956         ctl_done((union ctl_io *)ctsio);
957 }
958
959 /*
960  * For any sort of check condition, busy, etc., we just retry.  We do not
961  * decrement the retry count for unit attention type errors.  These are
962  * normal, and we want to save the retry count for "real" errors.  Otherwise,
963  * we could end up with situations where a command will succeed in some
964  * situations and fail in others, depending on whether a unit attention is
965  * pending.  Also, some of our error recovery actions, most notably the
966  * LUN reset action, will cause a unit attention.
967  *
968  * We can add more detail here later if necessary.
969  */
970 static tpc_error_action
971 tpc_checkcond_parse(union ctl_io *io)
972 {
973         tpc_error_action error_action;
974         int error_code, sense_key, asc, ascq;
975
976         /*
977          * Default to retrying the command.
978          */
979         error_action = TPC_ERR_RETRY;
980
981         scsi_extract_sense_len(&io->scsiio.sense_data,
982                                io->scsiio.sense_len,
983                                &error_code,
984                                &sense_key,
985                                &asc,
986                                &ascq,
987                                /*show_errors*/ 1);
988
989         switch (error_code) {
990         case SSD_DEFERRED_ERROR:
991         case SSD_DESC_DEFERRED_ERROR:
992                 error_action |= TPC_ERR_NO_DECREMENT;
993                 break;
994         case SSD_CURRENT_ERROR:
995         case SSD_DESC_CURRENT_ERROR:
996         default:
997                 switch (sense_key) {
998                 case SSD_KEY_UNIT_ATTENTION:
999                         error_action |= TPC_ERR_NO_DECREMENT;
1000                         break;
1001                 case SSD_KEY_HARDWARE_ERROR:
1002                         /*
1003                          * This is our generic "something bad happened"
1004                          * error code.  It often isn't recoverable.
1005                          */
1006                         if ((asc == 0x44) && (ascq == 0x00))
1007                                 error_action = TPC_ERR_FAIL;
1008                         break;
1009                 case SSD_KEY_NOT_READY:
1010                         /*
1011                          * If the LUN is powered down, there likely isn't
1012                          * much point in retrying right now.
1013                          */
1014                         if ((asc == 0x04) && (ascq == 0x02))
1015                                 error_action = TPC_ERR_FAIL;
1016                         /*
1017                          * If the LUN is offline, there probably isn't much
1018                          * point in retrying, either.
1019                          */
1020                         if ((asc == 0x04) && (ascq == 0x03))
1021                                 error_action = TPC_ERR_FAIL;
1022                         break;
1023                 }
1024         }
1025         return (error_action);
1026 }
1027
1028 static tpc_error_action
1029 tpc_error_parse(union ctl_io *io)
1030 {
1031         tpc_error_action error_action = TPC_ERR_RETRY;
1032
1033         switch (io->io_hdr.io_type) {
1034         case CTL_IO_SCSI:
1035                 switch (io->io_hdr.status & CTL_STATUS_MASK) {
1036                 case CTL_SCSI_ERROR:
1037                         switch (io->scsiio.scsi_status) {
1038                         case SCSI_STATUS_CHECK_COND:
1039                                 error_action = tpc_checkcond_parse(io);
1040                                 break;
1041                         default:
1042                                 break;
1043                         }
1044                         break;
1045                 default:
1046                         break;
1047                 }
1048                 break;
1049         case CTL_IO_TASK:
1050                 break;
1051         default:
1052                 panic("%s: invalid ctl_io type %d\n", __func__,
1053                       io->io_hdr.io_type);
1054                 break;
1055         }
1056         return (error_action);
1057 }
1058
1059 void
1060 tpc_done(union ctl_io *io)
1061 {
1062         struct tpc_io *tio, *tior;
1063
1064         /*
1065          * Very minimal retry logic.  We basically retry if we got an error
1066          * back, and the retry count is greater than 0.  If we ever want
1067          * more sophisticated initiator type behavior, the CAM error
1068          * recovery code in ../common might be helpful.
1069          */
1070 //      if ((io->io_hdr.status & CTL_STATUS_MASK) != CTL_SUCCESS)
1071 //              ctl_io_error_print(io, NULL);
1072         tio = io->io_hdr.ctl_private[CTL_PRIV_FRONTEND].ptr;
1073         if (((io->io_hdr.status & CTL_STATUS_MASK) != CTL_SUCCESS)
1074          && (io->io_hdr.retries > 0)) {
1075                 ctl_io_status old_status;
1076                 tpc_error_action error_action;
1077
1078                 error_action = tpc_error_parse(io);
1079                 switch (error_action & TPC_ERR_MASK) {
1080                 case TPC_ERR_FAIL:
1081                         break;
1082                 case TPC_ERR_RETRY:
1083                 default:
1084                         if ((error_action & TPC_ERR_NO_DECREMENT) == 0)
1085                                 io->io_hdr.retries--;
1086                         old_status = io->io_hdr.status;
1087                         io->io_hdr.status = CTL_STATUS_NONE;
1088                         io->io_hdr.flags &= ~CTL_FLAG_ABORT;
1089                         io->io_hdr.flags &= ~CTL_FLAG_SENT_2OTHER_SC;
1090                         if (tpcl_queue(io, tio->lun) != CTL_RETVAL_COMPLETE) {
1091                                 printf("%s: error returned from ctl_queue()!\n",
1092                                        __func__);
1093                                 io->io_hdr.status = old_status;
1094                         } else
1095                                 return;
1096                 }
1097         }
1098
1099         if ((io->io_hdr.status & CTL_STATUS_MASK) != CTL_SUCCESS)
1100                 tio->list->error = 1;
1101         else
1102                 atomic_add_int(&tio->list->curops, 1);
1103         if (!tio->list->error && !tio->list->abort) {
1104                 while ((tior = TAILQ_FIRST(&tio->run)) != NULL) {
1105                         TAILQ_REMOVE(&tio->run, tior, rlinks);
1106                         atomic_add_int(&tio->list->tbdio, 1);
1107                         if (tpcl_queue(tior->io, tior->lun) != CTL_RETVAL_COMPLETE)
1108                                 panic("tpcl_queue() error");
1109                 }
1110         }
1111         if (atomic_fetchadd_int(&tio->list->tbdio, -1) == 1)
1112                 tpc_process(tio->list);
1113 }
1114
1115 int
1116 ctl_extended_copy_lid1(struct ctl_scsiio *ctsio)
1117 {
1118         struct scsi_extended_copy *cdb;
1119         struct scsi_extended_copy_lid1_data *data;
1120         struct ctl_lun *lun;
1121         struct tpc_list *list, *tlist;
1122         uint8_t *ptr;
1123         char *value;
1124         int len, off, lencscd, lenseg, leninl, nseg;
1125
1126         CTL_DEBUG_PRINT(("ctl_extended_copy_lid1\n"));
1127
1128         lun = (struct ctl_lun *)ctsio->io_hdr.ctl_private[CTL_PRIV_LUN].ptr;
1129         cdb = (struct scsi_extended_copy *)ctsio->cdb;
1130         len = scsi_4btoul(cdb->length);
1131
1132         if (len < sizeof(struct scsi_extended_copy_lid1_data) ||
1133             len > sizeof(struct scsi_extended_copy_lid1_data) +
1134             TPC_MAX_LIST + TPC_MAX_INLINE) {
1135                 ctl_set_invalid_field(ctsio, /*sks_valid*/ 1, /*command*/ 1,
1136                     /*field*/ 9, /*bit_valid*/ 0, /*bit*/ 0);
1137                 goto done;
1138         }
1139
1140         /*
1141          * If we've got a kernel request that hasn't been malloced yet,
1142          * malloc it and tell the caller the data buffer is here.
1143          */
1144         if ((ctsio->io_hdr.flags & CTL_FLAG_ALLOCATED) == 0) {
1145                 ctsio->kern_data_ptr = malloc(len, M_CTL, M_WAITOK);
1146                 ctsio->kern_data_len = len;
1147                 ctsio->kern_total_len = len;
1148                 ctsio->kern_data_resid = 0;
1149                 ctsio->kern_rel_offset = 0;
1150                 ctsio->kern_sg_entries = 0;
1151                 ctsio->io_hdr.flags |= CTL_FLAG_ALLOCATED;
1152                 ctsio->be_move_done = ctl_config_move_done;
1153                 ctl_datamove((union ctl_io *)ctsio);
1154
1155                 return (CTL_RETVAL_COMPLETE);
1156         }
1157
1158         data = (struct scsi_extended_copy_lid1_data *)ctsio->kern_data_ptr;
1159         lencscd = scsi_2btoul(data->cscd_list_length);
1160         lenseg = scsi_4btoul(data->segment_list_length);
1161         leninl = scsi_4btoul(data->inline_data_length);
1162         if (len < sizeof(struct scsi_extended_copy_lid1_data) +
1163             lencscd + lenseg + leninl ||
1164             leninl > TPC_MAX_INLINE) {
1165                 ctl_set_invalid_field(ctsio, /*sks_valid*/ 1, /*command*/ 0,
1166                     /*field*/ 2, /*bit_valid*/ 0, /*bit*/ 0);
1167                 goto done;
1168         }
1169         if (lencscd > TPC_MAX_CSCDS * sizeof(struct scsi_ec_cscd)) {
1170                 ctl_set_sense(ctsio, /*current_error*/ 1,
1171                     /*sense_key*/ SSD_KEY_ILLEGAL_REQUEST,
1172                     /*asc*/ 0x26, /*ascq*/ 0x06, SSD_ELEM_NONE);
1173                 goto done;
1174         }
1175         if (lencscd + lenseg > TPC_MAX_LIST) {
1176                 ctl_set_param_len_error(ctsio);
1177                 goto done;
1178         }
1179
1180         list = malloc(sizeof(struct tpc_list), M_CTL, M_WAITOK | M_ZERO);
1181         list->service_action = cdb->service_action;
1182         value = ctl_get_opt(&lun->be_lun->options, "insecure_tpc");
1183         if (value != NULL && strcmp(value, "on") == 0)
1184                 list->init_port = -1;
1185         else
1186                 list->init_port = ctsio->io_hdr.nexus.targ_port;
1187         list->init_idx = ctl_get_resindex(&ctsio->io_hdr.nexus);
1188         list->list_id = data->list_identifier;
1189         list->flags = data->flags;
1190         list->params = ctsio->kern_data_ptr;
1191         list->cscd = (struct scsi_ec_cscd *)&data->data[0];
1192         ptr = &data->data[lencscd];
1193         for (nseg = 0, off = 0; off < lenseg; nseg++) {
1194                 if (nseg >= TPC_MAX_SEGS) {
1195                         free(list, M_CTL);
1196                         ctl_set_sense(ctsio, /*current_error*/ 1,
1197                             /*sense_key*/ SSD_KEY_ILLEGAL_REQUEST,
1198                             /*asc*/ 0x26, /*ascq*/ 0x08, SSD_ELEM_NONE);
1199                         goto done;
1200                 }
1201                 list->seg[nseg] = (struct scsi_ec_segment *)(ptr + off);
1202                 off += sizeof(struct scsi_ec_segment) +
1203                     scsi_2btoul(list->seg[nseg]->descr_length);
1204         }
1205         list->inl = &data->data[lencscd + lenseg];
1206         list->ncscd = lencscd / sizeof(struct scsi_ec_cscd);
1207         list->nseg = nseg;
1208         list->leninl = leninl;
1209         list->ctsio = ctsio;
1210         list->lun = lun;
1211         mtx_lock(&lun->lun_lock);
1212         if ((list->flags & EC_LIST_ID_USAGE_MASK) != EC_LIST_ID_USAGE_NONE) {
1213                 TAILQ_FOREACH(tlist, &lun->tpc_lists, links) {
1214                         if ((tlist->flags & EC_LIST_ID_USAGE_MASK) !=
1215                              EC_LIST_ID_USAGE_NONE &&
1216                             tlist->list_id == list->list_id)
1217                                 break;
1218                 }
1219                 if (tlist != NULL && !tlist->completed) {
1220                         mtx_unlock(&lun->lun_lock);
1221                         free(list, M_CTL);
1222                         ctl_set_invalid_field(ctsio, /*sks_valid*/ 1,
1223                             /*command*/ 0, /*field*/ 0, /*bit_valid*/ 0,
1224                             /*bit*/ 0);
1225                         goto done;
1226                 }
1227                 if (tlist != NULL) {
1228                         TAILQ_REMOVE(&lun->tpc_lists, tlist, links);
1229                         free(tlist, M_CTL);
1230                 }
1231         }
1232         TAILQ_INSERT_TAIL(&lun->tpc_lists, list, links);
1233         mtx_unlock(&lun->lun_lock);
1234
1235         tpc_process(list);
1236         return (CTL_RETVAL_COMPLETE);
1237
1238 done:
1239         ctl_done((union ctl_io *)ctsio);
1240         return (CTL_RETVAL_COMPLETE);
1241 }
1242
1243 int
1244 ctl_extended_copy_lid4(struct ctl_scsiio *ctsio)
1245 {
1246         struct scsi_extended_copy *cdb;
1247         struct scsi_extended_copy_lid4_data *data;
1248         struct ctl_lun *lun;
1249         struct tpc_list *list, *tlist;
1250         uint8_t *ptr;
1251         char *value;
1252         int len, off, lencscd, lenseg, leninl, nseg;
1253
1254         CTL_DEBUG_PRINT(("ctl_extended_copy_lid4\n"));
1255
1256         lun = (struct ctl_lun *)ctsio->io_hdr.ctl_private[CTL_PRIV_LUN].ptr;
1257         cdb = (struct scsi_extended_copy *)ctsio->cdb;
1258         len = scsi_4btoul(cdb->length);
1259
1260         if (len < sizeof(struct scsi_extended_copy_lid4_data) ||
1261             len > sizeof(struct scsi_extended_copy_lid4_data) +
1262             TPC_MAX_LIST + TPC_MAX_INLINE) {
1263                 ctl_set_invalid_field(ctsio, /*sks_valid*/ 1, /*command*/ 1,
1264                     /*field*/ 9, /*bit_valid*/ 0, /*bit*/ 0);
1265                 goto done;
1266         }
1267
1268         /*
1269          * If we've got a kernel request that hasn't been malloced yet,
1270          * malloc it and tell the caller the data buffer is here.
1271          */
1272         if ((ctsio->io_hdr.flags & CTL_FLAG_ALLOCATED) == 0) {
1273                 ctsio->kern_data_ptr = malloc(len, M_CTL, M_WAITOK);
1274                 ctsio->kern_data_len = len;
1275                 ctsio->kern_total_len = len;
1276                 ctsio->kern_data_resid = 0;
1277                 ctsio->kern_rel_offset = 0;
1278                 ctsio->kern_sg_entries = 0;
1279                 ctsio->io_hdr.flags |= CTL_FLAG_ALLOCATED;
1280                 ctsio->be_move_done = ctl_config_move_done;
1281                 ctl_datamove((union ctl_io *)ctsio);
1282
1283                 return (CTL_RETVAL_COMPLETE);
1284         }
1285
1286         data = (struct scsi_extended_copy_lid4_data *)ctsio->kern_data_ptr;
1287         lencscd = scsi_2btoul(data->cscd_list_length);
1288         lenseg = scsi_2btoul(data->segment_list_length);
1289         leninl = scsi_2btoul(data->inline_data_length);
1290         if (len < sizeof(struct scsi_extended_copy_lid4_data) +
1291             lencscd + lenseg + leninl ||
1292             leninl > TPC_MAX_INLINE) {
1293                 ctl_set_invalid_field(ctsio, /*sks_valid*/ 1, /*command*/ 0,
1294                     /*field*/ 2, /*bit_valid*/ 0, /*bit*/ 0);
1295                 goto done;
1296         }
1297         if (lencscd > TPC_MAX_CSCDS * sizeof(struct scsi_ec_cscd)) {
1298                 ctl_set_sense(ctsio, /*current_error*/ 1,
1299                     /*sense_key*/ SSD_KEY_ILLEGAL_REQUEST,
1300                     /*asc*/ 0x26, /*ascq*/ 0x06, SSD_ELEM_NONE);
1301                 goto done;
1302         }
1303         if (lencscd + lenseg > TPC_MAX_LIST) {
1304                 ctl_set_param_len_error(ctsio);
1305                 goto done;
1306         }
1307
1308         list = malloc(sizeof(struct tpc_list), M_CTL, M_WAITOK | M_ZERO);
1309         list->service_action = cdb->service_action;
1310         value = ctl_get_opt(&lun->be_lun->options, "insecure_tpc");
1311         if (value != NULL && strcmp(value, "on") == 0)
1312                 list->init_port = -1;
1313         else
1314                 list->init_port = ctsio->io_hdr.nexus.targ_port;
1315         list->init_idx = ctl_get_resindex(&ctsio->io_hdr.nexus);
1316         list->list_id = scsi_4btoul(data->list_identifier);
1317         list->flags = data->flags;
1318         list->params = ctsio->kern_data_ptr;
1319         list->cscd = (struct scsi_ec_cscd *)&data->data[0];
1320         ptr = &data->data[lencscd];
1321         for (nseg = 0, off = 0; off < lenseg; nseg++) {
1322                 if (nseg >= TPC_MAX_SEGS) {
1323                         free(list, M_CTL);
1324                         ctl_set_sense(ctsio, /*current_error*/ 1,
1325                             /*sense_key*/ SSD_KEY_ILLEGAL_REQUEST,
1326                             /*asc*/ 0x26, /*ascq*/ 0x08, SSD_ELEM_NONE);
1327                         goto done;
1328                 }
1329                 list->seg[nseg] = (struct scsi_ec_segment *)(ptr + off);
1330                 off += sizeof(struct scsi_ec_segment) +
1331                     scsi_2btoul(list->seg[nseg]->descr_length);
1332         }
1333         list->inl = &data->data[lencscd + lenseg];
1334         list->ncscd = lencscd / sizeof(struct scsi_ec_cscd);
1335         list->nseg = nseg;
1336         list->leninl = leninl;
1337         list->ctsio = ctsio;
1338         list->lun = lun;
1339         mtx_lock(&lun->lun_lock);
1340         if ((list->flags & EC_LIST_ID_USAGE_MASK) != EC_LIST_ID_USAGE_NONE) {
1341                 TAILQ_FOREACH(tlist, &lun->tpc_lists, links) {
1342                         if ((tlist->flags & EC_LIST_ID_USAGE_MASK) !=
1343                              EC_LIST_ID_USAGE_NONE &&
1344                             tlist->list_id == list->list_id)
1345                                 break;
1346                 }
1347                 if (tlist != NULL && !tlist->completed) {
1348                         mtx_unlock(&lun->lun_lock);
1349                         free(list, M_CTL);
1350                         ctl_set_invalid_field(ctsio, /*sks_valid*/ 1,
1351                             /*command*/ 0, /*field*/ 0, /*bit_valid*/ 0,
1352                             /*bit*/ 0);
1353                         goto done;
1354                 }
1355                 if (tlist != NULL) {
1356                         TAILQ_REMOVE(&lun->tpc_lists, tlist, links);
1357                         free(tlist, M_CTL);
1358                 }
1359         }
1360         TAILQ_INSERT_TAIL(&lun->tpc_lists, list, links);
1361         mtx_unlock(&lun->lun_lock);
1362
1363         tpc_process(list);
1364         return (CTL_RETVAL_COMPLETE);
1365
1366 done:
1367         ctl_done((union ctl_io *)ctsio);
1368         return (CTL_RETVAL_COMPLETE);
1369 }
1370