0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017 #include <linux/module.h>
0018 #include <linux/moduleparam.h>
0019 #include <linux/utsname.h>
0020 #include <linux/init.h>
0021 #include <linux/slab.h>
0022 #include <linux/kthread.h>
0023 #include <linux/types.h>
0024 #include <linux/string.h>
0025 #include <linux/configfs.h>
0026 #include <linux/ctype.h>
0027 #include <linux/hash.h>
0028 #include <linux/ratelimit.h>
0029 #include <asm/unaligned.h>
0030 #include <scsi/libfc.h>
0031
0032 #include <target/target_core_base.h>
0033 #include <target/target_core_fabric.h>
0034
0035 #include "tcm_fc.h"
0036
0037
0038
0039
0040
0041 int ft_queue_data_in(struct se_cmd *se_cmd)
0042 {
0043 struct ft_cmd *cmd = container_of(se_cmd, struct ft_cmd, se_cmd);
0044 struct fc_frame *fp = NULL;
0045 struct fc_exch *ep;
0046 struct fc_lport *lport;
0047 struct scatterlist *sg = NULL;
0048 size_t remaining;
0049 u32 f_ctl = FC_FC_EX_CTX | FC_FC_REL_OFF;
0050 u32 mem_off = 0;
0051 u32 fh_off = 0;
0052 u32 frame_off = 0;
0053 size_t frame_len = 0;
0054 size_t mem_len = 0;
0055 size_t tlen;
0056 size_t off_in_page;
0057 struct page *page = NULL;
0058 int use_sg;
0059 int error;
0060 void *page_addr;
0061 void *from;
0062 void *to = NULL;
0063
0064 if (cmd->aborted)
0065 return 0;
0066
0067 if (se_cmd->scsi_status == SAM_STAT_TASK_SET_FULL)
0068 goto queue_status;
0069
0070 ep = fc_seq_exch(cmd->seq);
0071 lport = ep->lp;
0072 cmd->seq = fc_seq_start_next(cmd->seq);
0073
0074 remaining = se_cmd->data_length;
0075
0076
0077
0078
0079 BUG_ON(remaining && !se_cmd->t_data_sg);
0080 if (remaining) {
0081 sg = se_cmd->t_data_sg;
0082 mem_len = sg->length;
0083 mem_off = sg->offset;
0084 page = sg_page(sg);
0085 }
0086
0087
0088 use_sg = !(remaining % 4);
0089
0090 while (remaining) {
0091 struct fc_seq *seq = cmd->seq;
0092
0093 if (!seq) {
0094 pr_debug("%s: Command aborted, xid 0x%x\n",
0095 __func__, ep->xid);
0096 break;
0097 }
0098 if (!mem_len) {
0099 sg = sg_next(sg);
0100 mem_len = min((size_t)sg->length, remaining);
0101 mem_off = sg->offset;
0102 page = sg_page(sg);
0103 }
0104 if (!frame_len) {
0105
0106
0107
0108
0109
0110 frame_len = (lport->seq_offload) ? lport->lso_max :
0111 cmd->sess->max_frame;
0112 frame_len = min(frame_len, remaining);
0113 fp = fc_frame_alloc(lport, use_sg ? 0 : frame_len);
0114 if (!fp)
0115 return -ENOMEM;
0116 to = fc_frame_payload_get(fp, 0);
0117 fh_off = frame_off;
0118 frame_off += frame_len;
0119
0120
0121
0122
0123
0124
0125 fr_max_payload(fp) = cmd->sess->max_frame;
0126 }
0127 tlen = min(mem_len, frame_len);
0128
0129 if (use_sg) {
0130 off_in_page = mem_off;
0131 BUG_ON(!page);
0132 get_page(page);
0133 skb_fill_page_desc(fp_skb(fp),
0134 skb_shinfo(fp_skb(fp))->nr_frags,
0135 page, off_in_page, tlen);
0136 fr_len(fp) += tlen;
0137 fp_skb(fp)->data_len += tlen;
0138 fp_skb(fp)->truesize += page_size(page);
0139 } else {
0140 BUG_ON(!page);
0141 from = kmap_atomic(page + (mem_off >> PAGE_SHIFT));
0142 page_addr = from;
0143 from += offset_in_page(mem_off);
0144 tlen = min(tlen, (size_t)(PAGE_SIZE -
0145 offset_in_page(mem_off)));
0146 memcpy(to, from, tlen);
0147 kunmap_atomic(page_addr);
0148 to += tlen;
0149 }
0150
0151 mem_off += tlen;
0152 mem_len -= tlen;
0153 frame_len -= tlen;
0154 remaining -= tlen;
0155
0156 if (frame_len &&
0157 (skb_shinfo(fp_skb(fp))->nr_frags < FC_FRAME_SG_LEN))
0158 continue;
0159 if (!remaining)
0160 f_ctl |= FC_FC_END_SEQ;
0161 fc_fill_fc_hdr(fp, FC_RCTL_DD_SOL_DATA, ep->did, ep->sid,
0162 FC_TYPE_FCP, f_ctl, fh_off);
0163 error = fc_seq_send(lport, seq, fp);
0164 if (error) {
0165 pr_info_ratelimited("%s: Failed to send frame %p, "
0166 "xid <0x%x>, remaining %zu, "
0167 "lso_max <0x%x>\n",
0168 __func__, fp, ep->xid,
0169 remaining, lport->lso_max);
0170
0171
0172
0173
0174
0175
0176
0177 se_cmd->scsi_status = SAM_STAT_TASK_SET_FULL;
0178 break;
0179 }
0180 }
0181 queue_status:
0182 return ft_queue_status(se_cmd);
0183 }
0184
0185 static void ft_execute_work(struct work_struct *work)
0186 {
0187 struct ft_cmd *cmd = container_of(work, struct ft_cmd, work);
0188
0189 target_execute_cmd(&cmd->se_cmd);
0190 }
0191
0192
0193
0194
0195 void ft_recv_write_data(struct ft_cmd *cmd, struct fc_frame *fp)
0196 {
0197 struct se_cmd *se_cmd = &cmd->se_cmd;
0198 struct fc_seq *seq = cmd->seq;
0199 struct fc_exch *ep;
0200 struct fc_lport *lport;
0201 struct fc_frame_header *fh;
0202 struct scatterlist *sg = NULL;
0203 u32 mem_off = 0;
0204 u32 rel_off;
0205 size_t frame_len;
0206 size_t mem_len = 0;
0207 size_t tlen;
0208 struct page *page = NULL;
0209 void *page_addr;
0210 void *from;
0211 void *to;
0212 u32 f_ctl;
0213 void *buf;
0214
0215 fh = fc_frame_header_get(fp);
0216 if (!(ntoh24(fh->fh_f_ctl) & FC_FC_REL_OFF))
0217 goto drop;
0218
0219 f_ctl = ntoh24(fh->fh_f_ctl);
0220 ep = fc_seq_exch(seq);
0221 lport = ep->lp;
0222 if (cmd->was_ddp_setup) {
0223 BUG_ON(!lport);
0224
0225
0226
0227
0228 buf = fc_frame_payload_get(fp, 1);
0229 if (buf)
0230 pr_err("%s: xid 0x%x, f_ctl 0x%x, cmd->sg %p, "
0231 "cmd->sg_cnt 0x%x. DDP was setup"
0232 " hence not expected to receive frame with "
0233 "payload, Frame will be dropped if"
0234 "'Sequence Initiative' bit in f_ctl is"
0235 "not set\n", __func__, ep->xid, f_ctl,
0236 se_cmd->t_data_sg, se_cmd->t_data_nents);
0237
0238
0239
0240
0241
0242 ft_invl_hw_context(cmd);
0243
0244
0245
0246
0247
0248
0249
0250
0251
0252
0253
0254 if (f_ctl & FC_FC_SEQ_INIT)
0255 goto last_frame;
0256 else
0257 goto drop;
0258 }
0259
0260 rel_off = ntohl(fh->fh_parm_offset);
0261 frame_len = fr_len(fp);
0262 if (frame_len <= sizeof(*fh))
0263 goto drop;
0264 frame_len -= sizeof(*fh);
0265 from = fc_frame_payload_get(fp, 0);
0266 if (rel_off >= se_cmd->data_length)
0267 goto drop;
0268 if (frame_len + rel_off > se_cmd->data_length)
0269 frame_len = se_cmd->data_length - rel_off;
0270
0271
0272
0273
0274 BUG_ON(frame_len && !se_cmd->t_data_sg);
0275 if (frame_len) {
0276 sg = se_cmd->t_data_sg;
0277 mem_len = sg->length;
0278 mem_off = sg->offset;
0279 page = sg_page(sg);
0280 }
0281
0282 while (frame_len) {
0283 if (!mem_len) {
0284 sg = sg_next(sg);
0285 mem_len = sg->length;
0286 mem_off = sg->offset;
0287 page = sg_page(sg);
0288 }
0289 if (rel_off >= mem_len) {
0290 rel_off -= mem_len;
0291 mem_len = 0;
0292 continue;
0293 }
0294 mem_off += rel_off;
0295 mem_len -= rel_off;
0296 rel_off = 0;
0297
0298 tlen = min(mem_len, frame_len);
0299
0300 to = kmap_atomic(page + (mem_off >> PAGE_SHIFT));
0301 page_addr = to;
0302 to += offset_in_page(mem_off);
0303 tlen = min(tlen, (size_t)(PAGE_SIZE -
0304 offset_in_page(mem_off)));
0305 memcpy(to, from, tlen);
0306 kunmap_atomic(page_addr);
0307
0308 from += tlen;
0309 frame_len -= tlen;
0310 mem_off += tlen;
0311 mem_len -= tlen;
0312 cmd->write_data_len += tlen;
0313 }
0314 last_frame:
0315 if (cmd->write_data_len == se_cmd->data_length) {
0316 INIT_WORK(&cmd->work, ft_execute_work);
0317 queue_work(cmd->sess->tport->tpg->workqueue, &cmd->work);
0318 }
0319 drop:
0320 fc_frame_free(fp);
0321 }
0322
0323
0324
0325
0326
0327 void ft_invl_hw_context(struct ft_cmd *cmd)
0328 {
0329 struct fc_seq *seq;
0330 struct fc_exch *ep = NULL;
0331 struct fc_lport *lport = NULL;
0332
0333 BUG_ON(!cmd);
0334 seq = cmd->seq;
0335
0336
0337 if (cmd->was_ddp_setup && seq) {
0338 ep = fc_seq_exch(seq);
0339 if (ep) {
0340 lport = ep->lp;
0341 if (lport && (ep->xid <= lport->lro_xid)) {
0342
0343
0344
0345
0346 cmd->write_data_len = lport->tt.ddp_done(lport,
0347 ep->xid);
0348
0349
0350
0351
0352
0353
0354
0355 cmd->was_ddp_setup = 0;
0356 }
0357 }
0358 }
0359 }