1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20#include <linux/module.h>
21#include <linux/moduleparam.h>
22#include <linux/utsname.h>
23#include <linux/init.h>
24#include <linux/slab.h>
25#include <linux/kthread.h>
26#include <linux/types.h>
27#include <linux/string.h>
28#include <linux/configfs.h>
29#include <linux/ctype.h>
30#include <linux/hash.h>
31#include <asm/unaligned.h>
32#include <scsi/scsi.h>
33#include <scsi/scsi_host.h>
34#include <scsi/scsi_device.h>
35#include <scsi/scsi_cmnd.h>
36#include <scsi/scsi_tcq.h>
37#include <scsi/libfc.h>
38#include <scsi/fc_encode.h>
39
40#include <target/target_core_base.h>
41#include <target/target_core_fabric.h>
42#include <target/target_core_configfs.h>
43#include <target/configfs_macros.h>
44
45#include "tcm_fc.h"
46
47
48
49
50static void _ft_dump_cmd(struct ft_cmd *cmd, const char *caller)
51{
52 struct fc_exch *ep;
53 struct fc_seq *sp;
54 struct se_cmd *se_cmd;
55 struct scatterlist *sg;
56 int count;
57
58 se_cmd = &cmd->se_cmd;
59 pr_debug("%s: cmd %p sess %p seq %p se_cmd %p\n",
60 caller, cmd, cmd->sess, cmd->seq, se_cmd);
61
62 pr_debug("%s: cmd %p data_nents %u len %u se_cmd_flags <0x%x>\n",
63 caller, cmd, se_cmd->t_data_nents,
64 se_cmd->data_length, se_cmd->se_cmd_flags);
65
66 for_each_sg(se_cmd->t_data_sg, sg, se_cmd->t_data_nents, count)
67 pr_debug("%s: cmd %p sg %p page %p "
68 "len 0x%x off 0x%x\n",
69 caller, cmd, sg,
70 sg_page(sg), sg->length, sg->offset);
71
72 sp = cmd->seq;
73 if (sp) {
74 ep = fc_seq_exch(sp);
75 pr_debug("%s: cmd %p sid %x did %x "
76 "ox_id %x rx_id %x seq_id %x e_stat %x\n",
77 caller, cmd, ep->sid, ep->did, ep->oxid, ep->rxid,
78 sp->id, ep->esb_stat);
79 }
80}
81
82void ft_dump_cmd(struct ft_cmd *cmd, const char *caller)
83{
84 if (unlikely(ft_debug_logging))
85 _ft_dump_cmd(cmd, caller);
86}
87
88static void ft_free_cmd(struct ft_cmd *cmd)
89{
90 struct fc_frame *fp;
91 struct fc_lport *lport;
92
93 if (!cmd)
94 return;
95 fp = cmd->req_frame;
96 lport = fr_dev(fp);
97 if (fr_seq(fp))
98 lport->tt.seq_release(fr_seq(fp));
99 fc_frame_free(fp);
100 ft_sess_put(cmd->sess);
101 kfree(cmd);
102}
103
104void ft_release_cmd(struct se_cmd *se_cmd)
105{
106 struct ft_cmd *cmd = container_of(se_cmd, struct ft_cmd, se_cmd);
107
108 ft_free_cmd(cmd);
109}
110
111int ft_check_stop_free(struct se_cmd *se_cmd)
112{
113 transport_generic_free_cmd(se_cmd, 0);
114 return 1;
115}
116
117
118
119
120int ft_queue_status(struct se_cmd *se_cmd)
121{
122 struct ft_cmd *cmd = container_of(se_cmd, struct ft_cmd, se_cmd);
123 struct fc_frame *fp;
124 struct fcp_resp_with_ext *fcp;
125 struct fc_lport *lport;
126 struct fc_exch *ep;
127 size_t len;
128
129 if (cmd->aborted)
130 return 0;
131 ft_dump_cmd(cmd, __func__);
132 ep = fc_seq_exch(cmd->seq);
133 lport = ep->lp;
134 len = sizeof(*fcp) + se_cmd->scsi_sense_length;
135 fp = fc_frame_alloc(lport, len);
136 if (!fp) {
137
138 return 0;
139 }
140 fcp = fc_frame_payload_get(fp, len);
141 memset(fcp, 0, len);
142 fcp->resp.fr_status = se_cmd->scsi_status;
143
144 len = se_cmd->scsi_sense_length;
145 if (len) {
146 fcp->resp.fr_flags |= FCP_SNS_LEN_VAL;
147 fcp->ext.fr_sns_len = htonl(len);
148 memcpy((fcp + 1), se_cmd->sense_buffer, len);
149 }
150
151
152
153
154
155 if (se_cmd->se_cmd_flags & (SCF_OVERFLOW_BIT | SCF_UNDERFLOW_BIT)) {
156 if (se_cmd->se_cmd_flags & SCF_OVERFLOW_BIT)
157 fcp->resp.fr_flags |= FCP_RESID_OVER;
158 else
159 fcp->resp.fr_flags |= FCP_RESID_UNDER;
160 fcp->ext.fr_resid = cpu_to_be32(se_cmd->residual_count);
161 }
162
163
164
165
166 cmd->seq = lport->tt.seq_start_next(cmd->seq);
167 fc_fill_fc_hdr(fp, FC_RCTL_DD_CMD_STATUS, ep->did, ep->sid, FC_TYPE_FCP,
168 FC_FC_EX_CTX | FC_FC_LAST_SEQ | FC_FC_END_SEQ, 0);
169
170 lport->tt.seq_send(lport, cmd->seq, fp);
171 lport->tt.exch_done(cmd->seq);
172 return 0;
173}
174
175int ft_write_pending_status(struct se_cmd *se_cmd)
176{
177 struct ft_cmd *cmd = container_of(se_cmd, struct ft_cmd, se_cmd);
178
179 return cmd->write_data_len != se_cmd->data_length;
180}
181
182
183
184
185int ft_write_pending(struct se_cmd *se_cmd)
186{
187 struct ft_cmd *cmd = container_of(se_cmd, struct ft_cmd, se_cmd);
188 struct fc_frame *fp;
189 struct fcp_txrdy *txrdy;
190 struct fc_lport *lport;
191 struct fc_exch *ep;
192 struct fc_frame_header *fh;
193 u32 f_ctl;
194
195 ft_dump_cmd(cmd, __func__);
196
197 if (cmd->aborted)
198 return 0;
199 ep = fc_seq_exch(cmd->seq);
200 lport = ep->lp;
201 fp = fc_frame_alloc(lport, sizeof(*txrdy));
202 if (!fp)
203 return -ENOMEM;
204
205 txrdy = fc_frame_payload_get(fp, sizeof(*txrdy));
206 memset(txrdy, 0, sizeof(*txrdy));
207 txrdy->ft_burst_len = htonl(se_cmd->data_length);
208
209 cmd->seq = lport->tt.seq_start_next(cmd->seq);
210 fc_fill_fc_hdr(fp, FC_RCTL_DD_DATA_DESC, ep->did, ep->sid, FC_TYPE_FCP,
211 FC_FC_EX_CTX | FC_FC_END_SEQ | FC_FC_SEQ_INIT, 0);
212
213 fh = fc_frame_header_get(fp);
214 f_ctl = ntoh24(fh->fh_f_ctl);
215
216
217 if (f_ctl & FC_FC_EX_CTX) {
218
219
220
221 if ((ep->xid <= lport->lro_xid) &&
222 (fh->fh_r_ctl == FC_RCTL_DD_DATA_DESC)) {
223 if ((se_cmd->se_cmd_flags & SCF_SCSI_DATA_CDB) &&
224 lport->tt.ddp_target(lport, ep->xid,
225 se_cmd->t_data_sg,
226 se_cmd->t_data_nents))
227 cmd->was_ddp_setup = 1;
228 }
229 }
230 lport->tt.seq_send(lport, cmd->seq, fp);
231 return 0;
232}
233
234u32 ft_get_task_tag(struct se_cmd *se_cmd)
235{
236 struct ft_cmd *cmd = container_of(se_cmd, struct ft_cmd, se_cmd);
237
238 if (cmd->aborted)
239 return ~0;
240 return fc_seq_exch(cmd->seq)->rxid;
241}
242
243int ft_get_cmd_state(struct se_cmd *se_cmd)
244{
245 return 0;
246}
247
248
249
250
251static void ft_recv_seq(struct fc_seq *sp, struct fc_frame *fp, void *arg)
252{
253 struct ft_cmd *cmd = arg;
254 struct fc_frame_header *fh;
255
256 if (unlikely(IS_ERR(fp))) {
257
258 cmd->seq = NULL;
259 cmd->aborted = true;
260 return;
261 }
262
263 fh = fc_frame_header_get(fp);
264
265 switch (fh->fh_r_ctl) {
266 case FC_RCTL_DD_SOL_DATA:
267 ft_recv_write_data(cmd, fp);
268 break;
269 case FC_RCTL_DD_UNSOL_CTL:
270 case FC_RCTL_DD_SOL_CTL:
271 case FC_RCTL_DD_DATA_DESC:
272 default:
273 pr_debug("%s: unhandled frame r_ctl %x\n",
274 __func__, fh->fh_r_ctl);
275 ft_invl_hw_context(cmd);
276 fc_frame_free(fp);
277 transport_generic_free_cmd(&cmd->se_cmd, 0);
278 break;
279 }
280}
281
282
283
284
285
286
287static void ft_send_resp_status(struct fc_lport *lport,
288 const struct fc_frame *rx_fp,
289 u32 status, enum fcp_resp_rsp_codes code)
290{
291 struct fc_frame *fp;
292 struct fc_seq *sp;
293 const struct fc_frame_header *fh;
294 size_t len;
295 struct fcp_resp_with_ext *fcp;
296 struct fcp_resp_rsp_info *info;
297
298 fh = fc_frame_header_get(rx_fp);
299 pr_debug("FCP error response: did %x oxid %x status %x code %x\n",
300 ntoh24(fh->fh_s_id), ntohs(fh->fh_ox_id), status, code);
301 len = sizeof(*fcp);
302 if (status == SAM_STAT_GOOD)
303 len += sizeof(*info);
304 fp = fc_frame_alloc(lport, len);
305 if (!fp)
306 return;
307 fcp = fc_frame_payload_get(fp, len);
308 memset(fcp, 0, len);
309 fcp->resp.fr_status = status;
310 if (status == SAM_STAT_GOOD) {
311 fcp->ext.fr_rsp_len = htonl(sizeof(*info));
312 fcp->resp.fr_flags |= FCP_RSP_LEN_VAL;
313 info = (struct fcp_resp_rsp_info *)(fcp + 1);
314 info->rsp_code = code;
315 }
316
317 fc_fill_reply_hdr(fp, rx_fp, FC_RCTL_DD_CMD_STATUS, 0);
318 sp = fr_seq(fp);
319 if (sp) {
320 lport->tt.seq_send(lport, sp, fp);
321 lport->tt.exch_done(sp);
322 } else {
323 lport->tt.frame_send(lport, fp);
324 }
325}
326
327
328
329
330static void ft_send_resp_code(struct ft_cmd *cmd,
331 enum fcp_resp_rsp_codes code)
332{
333 ft_send_resp_status(cmd->sess->tport->lport,
334 cmd->req_frame, SAM_STAT_GOOD, code);
335}
336
337
338
339
340
341
342static void ft_send_resp_code_and_free(struct ft_cmd *cmd,
343 enum fcp_resp_rsp_codes code)
344{
345 ft_send_resp_code(cmd, code);
346 ft_free_cmd(cmd);
347}
348
349
350
351
352static void ft_send_tm(struct ft_cmd *cmd)
353{
354 struct fcp_cmnd *fcp;
355 int rc;
356 u8 tm_func;
357
358 fcp = fc_frame_payload_get(cmd->req_frame, sizeof(*fcp));
359
360 switch (fcp->fc_tm_flags) {
361 case FCP_TMF_LUN_RESET:
362 tm_func = TMR_LUN_RESET;
363 break;
364 case FCP_TMF_TGT_RESET:
365 tm_func = TMR_TARGET_WARM_RESET;
366 break;
367 case FCP_TMF_CLR_TASK_SET:
368 tm_func = TMR_CLEAR_TASK_SET;
369 break;
370 case FCP_TMF_ABT_TASK_SET:
371 tm_func = TMR_ABORT_TASK_SET;
372 break;
373 case FCP_TMF_CLR_ACA:
374 tm_func = TMR_CLEAR_ACA;
375 break;
376 default:
377
378
379
380
381 pr_debug("invalid FCP tm_flags %x\n", fcp->fc_tm_flags);
382 ft_send_resp_code_and_free(cmd, FCP_CMND_FIELDS_INVALID);
383 return;
384 }
385
386
387 rc = target_submit_tmr(&cmd->se_cmd, cmd->sess->se_sess,
388 &cmd->ft_sense_buffer[0], scsilun_to_int(&fcp->fc_lun),
389 cmd, tm_func, GFP_KERNEL, 0, 0);
390 if (rc < 0)
391 ft_send_resp_code_and_free(cmd, FCP_TMF_FAILED);
392}
393
394
395
396
397void ft_queue_tm_resp(struct se_cmd *se_cmd)
398{
399 struct ft_cmd *cmd = container_of(se_cmd, struct ft_cmd, se_cmd);
400 struct se_tmr_req *tmr = se_cmd->se_tmr_req;
401 enum fcp_resp_rsp_codes code;
402
403 if (cmd->aborted)
404 return;
405 switch (tmr->response) {
406 case TMR_FUNCTION_COMPLETE:
407 code = FCP_TMF_CMPL;
408 break;
409 case TMR_LUN_DOES_NOT_EXIST:
410 code = FCP_TMF_INVALID_LUN;
411 break;
412 case TMR_FUNCTION_REJECTED:
413 code = FCP_TMF_REJECTED;
414 break;
415 case TMR_TASK_DOES_NOT_EXIST:
416 case TMR_TASK_MGMT_FUNCTION_NOT_SUPPORTED:
417 default:
418 code = FCP_TMF_FAILED;
419 break;
420 }
421 pr_debug("tmr fn %d resp %d fcp code %d\n",
422 tmr->function, tmr->response, code);
423 ft_send_resp_code(cmd, code);
424}
425
426static void ft_send_work(struct work_struct *work);
427
428
429
430
431static void ft_recv_cmd(struct ft_sess *sess, struct fc_frame *fp)
432{
433 struct ft_cmd *cmd;
434 struct fc_lport *lport = sess->tport->lport;
435
436 cmd = kzalloc(sizeof(*cmd), GFP_ATOMIC);
437 if (!cmd)
438 goto busy;
439 cmd->sess = sess;
440 cmd->seq = lport->tt.seq_assign(lport, fp);
441 if (!cmd->seq) {
442 kfree(cmd);
443 goto busy;
444 }
445 cmd->req_frame = fp;
446
447 INIT_WORK(&cmd->work, ft_send_work);
448 queue_work(sess->tport->tpg->workqueue, &cmd->work);
449 return;
450
451busy:
452 pr_debug("cmd or seq allocation failure - sending BUSY\n");
453 ft_send_resp_status(lport, fp, SAM_STAT_BUSY, 0);
454 fc_frame_free(fp);
455 ft_sess_put(sess);
456}
457
458
459
460
461
462
463void ft_recv_req(struct ft_sess *sess, struct fc_frame *fp)
464{
465 struct fc_frame_header *fh = fc_frame_header_get(fp);
466
467 switch (fh->fh_r_ctl) {
468 case FC_RCTL_DD_UNSOL_CMD:
469 ft_recv_cmd(sess, fp);
470 break;
471 case FC_RCTL_DD_SOL_DATA:
472 case FC_RCTL_DD_UNSOL_CTL:
473 case FC_RCTL_DD_SOL_CTL:
474 case FC_RCTL_DD_DATA_DESC:
475 case FC_RCTL_ELS4_REQ:
476 default:
477 pr_debug("%s: unhandled frame r_ctl %x\n",
478 __func__, fh->fh_r_ctl);
479 fc_frame_free(fp);
480 ft_sess_put(sess);
481 break;
482 }
483}
484
485
486
487
488static void ft_send_work(struct work_struct *work)
489{
490 struct ft_cmd *cmd = container_of(work, struct ft_cmd, work);
491 struct fc_frame_header *fh = fc_frame_header_get(cmd->req_frame);
492 struct fcp_cmnd *fcp;
493 int data_dir = 0;
494 int task_attr;
495
496 fcp = fc_frame_payload_get(cmd->req_frame, sizeof(*fcp));
497 if (!fcp)
498 goto err;
499
500 if (fcp->fc_flags & FCP_CFL_LEN_MASK)
501 goto err;
502
503
504
505
506 if (fcp->fc_tm_flags) {
507 ft_send_tm(cmd);
508 return;
509 }
510
511 switch (fcp->fc_flags & (FCP_CFL_RDDATA | FCP_CFL_WRDATA)) {
512 case 0:
513 data_dir = DMA_NONE;
514 break;
515 case FCP_CFL_RDDATA:
516 data_dir = DMA_FROM_DEVICE;
517 break;
518 case FCP_CFL_WRDATA:
519 data_dir = DMA_TO_DEVICE;
520 break;
521 case FCP_CFL_WRDATA | FCP_CFL_RDDATA:
522 goto err;
523 }
524
525
526
527 switch (fcp->fc_pri_ta & FCP_PTA_MASK) {
528 case FCP_PTA_HEADQ:
529 task_attr = MSG_HEAD_TAG;
530 break;
531 case FCP_PTA_ORDERED:
532 task_attr = MSG_ORDERED_TAG;
533 break;
534 case FCP_PTA_ACA:
535 task_attr = MSG_ACA_TAG;
536 break;
537 case FCP_PTA_SIMPLE:
538 default:
539 task_attr = MSG_SIMPLE_TAG;
540 }
541
542 fc_seq_exch(cmd->seq)->lp->tt.seq_set_resp(cmd->seq, ft_recv_seq, cmd);
543
544
545
546
547 if (target_submit_cmd(&cmd->se_cmd, cmd->sess->se_sess, fcp->fc_cdb,
548 &cmd->ft_sense_buffer[0], scsilun_to_int(&fcp->fc_lun),
549 ntohl(fcp->fc_dl), task_attr, data_dir, 0))
550 goto err;
551
552 pr_debug("r_ctl %x alloc target_submit_cmd\n", fh->fh_r_ctl);
553 return;
554
555err:
556 ft_send_resp_code_and_free(cmd, FCP_CMND_FIELDS_INVALID);
557}
558