1// SPDX-License-Identifier: GPL-2.0
2/*
3 * Copyright (C) 2021 Broadcom. All Rights Reserved. The term
4 * “Broadcom” refers to Broadcom Inc. and/or its subsidiaries.
5 */
6
7#include "efct_driver.h"
8#include "efct_unsol.h"
9
10#define frame_printf(efct, hdr, fmt, ...) \
11 do { \
12 char s_id_text[16]; \
13 efc_node_fcid_display(ntoh24((hdr)->fh_s_id), \
14 s_id_text, sizeof(s_id_text)); \
15 efc_log_debug(efct, "[%06x.%s] %02x/%04x/%04x: " fmt, \
16 ntoh24((hdr)->fh_d_id), s_id_text, \
17 (hdr)->fh_r_ctl, be16_to_cpu((hdr)->fh_ox_id), \
18 be16_to_cpu((hdr)->fh_rx_id), ##__VA_ARGS__); \
19 } while (0)
20
21static struct efct_node *
22efct_node_find(struct efct *efct, u32 port_id, u32 node_id)
23{
24 struct efct_node *node;
25 u64 id = (u64)port_id << 32 | node_id;
26
27 /*
28 * During node shutdown, Lookup will be removed first,
29 * before announcing to backend. So, no new IOs will be allowed
30 */
31 /* Find a target node, given s_id and d_id */
32 node = xa_load(&efct->lookup, index: id);
33 if (node)
34 kref_get(kref: &node->ref);
35
36 return node;
37}
38
39static int
40efct_dispatch_frame(struct efct *efct, struct efc_hw_sequence *seq)
41{
42 struct efct_node *node;
43 struct fc_frame_header *hdr;
44 u32 s_id, d_id;
45
46 hdr = seq->header->dma.virt;
47
48 /* extract the s_id and d_id */
49 s_id = ntoh24(p: hdr->fh_s_id);
50 d_id = ntoh24(p: hdr->fh_d_id);
51
52 if (!(hdr->fh_type == FC_TYPE_FCP || hdr->fh_type == FC_TYPE_BLS))
53 return -EIO;
54
55 if (hdr->fh_type == FC_TYPE_FCP) {
56 node = efct_node_find(efct, port_id: d_id, node_id: s_id);
57 if (!node) {
58 efc_log_err(efct,
59 "Node not found, drop cmd d_id:%x s_id:%x\n",
60 d_id, s_id);
61 efct_hw_sequence_free(hw: &efct->hw, seq);
62 return 0;
63 }
64
65 efct_dispatch_fcp_cmd(node, seq);
66 } else {
67 node = efct_node_find(efct, port_id: d_id, node_id: s_id);
68 if (!node) {
69 efc_log_err(efct, "ABTS: Node not found, d_id:%x s_id:%x\n",
70 d_id, s_id);
71 return -EIO;
72 }
73
74 efc_log_err(efct, "Received ABTS for Node:%p\n", node);
75 efct_node_recv_abts_frame(node, seq);
76 }
77
78 kref_put(kref: &node->ref, release: node->release);
79 efct_hw_sequence_free(hw: &efct->hw, seq);
80 return 0;
81}
82
83int
84efct_unsolicited_cb(void *arg, struct efc_hw_sequence *seq)
85{
86 struct efct *efct = arg;
87
88 /* Process FCP command */
89 if (!efct_dispatch_frame(efct, seq))
90 return 0;
91
92 /* Forward frame to discovery lib */
93 efc_dispatch_frame(efc: efct->efcport, seq);
94 return 0;
95}
96
97static int
98efct_fc_tmf_rejected_cb(struct efct_io *io,
99 enum efct_scsi_io_status scsi_status,
100 u32 flags, void *arg)
101{
102 efct_scsi_io_free(io);
103 return 0;
104}
105
106static void
107efct_dispatch_unsol_tmf(struct efct_io *io, u8 tm_flags, u32 lun)
108{
109 u32 i;
110 struct {
111 u32 mask;
112 enum efct_scsi_tmf_cmd cmd;
113 } tmflist[] = {
114 {FCP_TMF_ABT_TASK_SET, EFCT_SCSI_TMF_ABORT_TASK_SET},
115 {FCP_TMF_CLR_TASK_SET, EFCT_SCSI_TMF_CLEAR_TASK_SET},
116 {FCP_TMF_LUN_RESET, EFCT_SCSI_TMF_LOGICAL_UNIT_RESET},
117 {FCP_TMF_TGT_RESET, EFCT_SCSI_TMF_TARGET_RESET},
118 {FCP_TMF_CLR_ACA, EFCT_SCSI_TMF_CLEAR_ACA} };
119
120 io->exp_xfer_len = 0;
121
122 for (i = 0; i < ARRAY_SIZE(tmflist); i++) {
123 if (tmflist[i].mask & tm_flags) {
124 io->tmf_cmd = tmflist[i].cmd;
125 efct_scsi_recv_tmf(tmfio: io, lun, cmd: tmflist[i].cmd, NULL, flags: 0);
126 break;
127 }
128 }
129 if (i == ARRAY_SIZE(tmflist)) {
130 /* Not handled */
131 efc_log_err(io->node->efct, "TMF x%x rejected\n", tm_flags);
132 efct_scsi_send_tmf_resp(io, rspcode: EFCT_SCSI_TMF_FUNCTION_REJECTED,
133 NULL, cb: efct_fc_tmf_rejected_cb, NULL);
134 }
135}
136
137static int
138efct_validate_fcp_cmd(struct efct *efct, struct efc_hw_sequence *seq)
139{
140 /*
141 * If we received less than FCP_CMND_IU bytes, assume that the frame is
142 * corrupted in some way and drop it.
143 * This was seen when jamming the FCTL
144 * fill bytes field.
145 */
146 if (seq->payload->dma.len < sizeof(struct fcp_cmnd)) {
147 struct fc_frame_header *fchdr = seq->header->dma.virt;
148
149 efc_log_debug(efct,
150 "drop ox_id %04x payload (%zd) less than (%zd)\n",
151 be16_to_cpu(fchdr->fh_ox_id),
152 seq->payload->dma.len, sizeof(struct fcp_cmnd));
153 return -EIO;
154 }
155 return 0;
156}
157
158static void
159efct_populate_io_fcp_cmd(struct efct_io *io, struct fcp_cmnd *cmnd,
160 struct fc_frame_header *fchdr, bool sit)
161{
162 io->init_task_tag = be16_to_cpu(fchdr->fh_ox_id);
163 /* note, tgt_task_tag, hw_tag set when HW io is allocated */
164 io->exp_xfer_len = be32_to_cpu(cmnd->fc_dl);
165 io->transferred = 0;
166
167 /* The upper 7 bits of CS_CTL is the frame priority thru the SAN.
168 * Our assertion here is, the priority given to a frame containing
169 * the FCP cmd should be the priority given to ALL frames contained
170 * in that IO. Thus we need to save the incoming CS_CTL here.
171 */
172 if (ntoh24(p: fchdr->fh_f_ctl) & FC_FC_RES_B17)
173 io->cs_ctl = fchdr->fh_cs_ctl;
174 else
175 io->cs_ctl = 0;
176
177 io->seq_init = sit;
178}
179
180static u32
181efct_get_flags_fcp_cmd(struct fcp_cmnd *cmnd)
182{
183 u32 flags = 0;
184
185 switch (cmnd->fc_pri_ta & FCP_PTA_MASK) {
186 case FCP_PTA_SIMPLE:
187 flags |= EFCT_SCSI_CMD_SIMPLE;
188 break;
189 case FCP_PTA_HEADQ:
190 flags |= EFCT_SCSI_CMD_HEAD_OF_QUEUE;
191 break;
192 case FCP_PTA_ORDERED:
193 flags |= EFCT_SCSI_CMD_ORDERED;
194 break;
195 case FCP_PTA_ACA:
196 flags |= EFCT_SCSI_CMD_ACA;
197 break;
198 }
199 if (cmnd->fc_flags & FCP_CFL_WRDATA)
200 flags |= EFCT_SCSI_CMD_DIR_IN;
201 if (cmnd->fc_flags & FCP_CFL_RDDATA)
202 flags |= EFCT_SCSI_CMD_DIR_OUT;
203
204 return flags;
205}
206
207static void
208efct_sframe_common_send_cb(void *arg, u8 *cqe, int status)
209{
210 struct efct_hw_send_frame_context *ctx = arg;
211 struct efct_hw *hw = ctx->hw;
212
213 /* Free WQ completion callback */
214 efct_hw_reqtag_free(hw, wqcb: ctx->wqcb);
215
216 /* Free sequence */
217 efct_hw_sequence_free(hw, seq: ctx->seq);
218}
219
220static int
221efct_sframe_common_send(struct efct_node *node,
222 struct efc_hw_sequence *seq,
223 enum fc_rctl r_ctl, u32 f_ctl,
224 u8 type, void *payload, u32 payload_len)
225{
226 struct efct *efct = node->efct;
227 struct efct_hw *hw = &efct->hw;
228 int rc = 0;
229 struct fc_frame_header *req_hdr = seq->header->dma.virt;
230 struct fc_frame_header hdr;
231 struct efct_hw_send_frame_context *ctx;
232
233 u32 heap_size = seq->payload->dma.size;
234 uintptr_t heap_phys_base = seq->payload->dma.phys;
235 u8 *heap_virt_base = seq->payload->dma.virt;
236 u32 heap_offset = 0;
237
238 /* Build the FC header reusing the RQ header DMA buffer */
239 memset(&hdr, 0, sizeof(hdr));
240 hdr.fh_r_ctl = r_ctl;
241 /* send it back to whomever sent it to us */
242 memcpy(hdr.fh_d_id, req_hdr->fh_s_id, sizeof(hdr.fh_d_id));
243 memcpy(hdr.fh_s_id, req_hdr->fh_d_id, sizeof(hdr.fh_s_id));
244 hdr.fh_type = type;
245 hton24(p: hdr.fh_f_ctl, v: f_ctl);
246 hdr.fh_ox_id = req_hdr->fh_ox_id;
247 hdr.fh_rx_id = req_hdr->fh_rx_id;
248 hdr.fh_cs_ctl = 0;
249 hdr.fh_df_ctl = 0;
250 hdr.fh_seq_cnt = 0;
251 hdr.fh_parm_offset = 0;
252
253 /*
254 * send_frame_seq_id is an atomic, we just let it increment,
255 * while storing only the low 8 bits to hdr->seq_id
256 */
257 hdr.fh_seq_id = (u8)atomic_add_return(i: 1, v: &hw->send_frame_seq_id);
258 hdr.fh_seq_id--;
259
260 /* Allocate and fill in the send frame request context */
261 ctx = (void *)(heap_virt_base + heap_offset);
262 heap_offset += sizeof(*ctx);
263 if (heap_offset > heap_size) {
264 efc_log_err(efct, "Fill send frame failed offset %d size %d\n",
265 heap_offset, heap_size);
266 return -EIO;
267 }
268
269 memset(ctx, 0, sizeof(*ctx));
270
271 /* Save sequence */
272 ctx->seq = seq;
273
274 /* Allocate a response payload DMA buffer from the heap */
275 ctx->payload.phys = heap_phys_base + heap_offset;
276 ctx->payload.virt = heap_virt_base + heap_offset;
277 ctx->payload.size = payload_len;
278 ctx->payload.len = payload_len;
279 heap_offset += payload_len;
280 if (heap_offset > heap_size) {
281 efc_log_err(efct, "Fill send frame failed offset %d size %d\n",
282 heap_offset, heap_size);
283 return -EIO;
284 }
285
286 /* Copy the payload in */
287 memcpy(ctx->payload.virt, payload, payload_len);
288
289 /* Send */
290 rc = efct_hw_send_frame(hw: &efct->hw, hdr: (void *)&hdr, sof: FC_SOF_N3,
291 eof: FC_EOF_T, payload: &ctx->payload, ctx,
292 callback: efct_sframe_common_send_cb, arg: ctx);
293 if (rc)
294 efc_log_debug(efct, "efct_hw_send_frame failed: %d\n", rc);
295
296 return rc;
297}
298
299static int
300efct_sframe_send_fcp_rsp(struct efct_node *node, struct efc_hw_sequence *seq,
301 void *rsp, u32 rsp_len)
302{
303 return efct_sframe_common_send(node, seq, r_ctl: FC_RCTL_DD_CMD_STATUS,
304 FC_FC_EX_CTX |
305 FC_FC_LAST_SEQ |
306 FC_FC_END_SEQ |
307 FC_FC_SEQ_INIT,
308 type: FC_TYPE_FCP,
309 payload: rsp, payload_len: rsp_len);
310}
311
312static int
313efct_sframe_send_task_set_full_or_busy(struct efct_node *node,
314 struct efc_hw_sequence *seq)
315{
316 struct fcp_resp_with_ext fcprsp;
317 struct fcp_cmnd *fcpcmd = seq->payload->dma.virt;
318 int rc = 0;
319 unsigned long flags = 0;
320 struct efct *efct = node->efct;
321
322 /* construct task set full or busy response */
323 memset(&fcprsp, 0, sizeof(fcprsp));
324 spin_lock_irqsave(&node->active_ios_lock, flags);
325 fcprsp.resp.fr_status = list_empty(head: &node->active_ios) ?
326 SAM_STAT_BUSY : SAM_STAT_TASK_SET_FULL;
327 spin_unlock_irqrestore(lock: &node->active_ios_lock, flags);
328 *((u32 *)&fcprsp.ext.fr_resid) = be32_to_cpu(fcpcmd->fc_dl);
329
330 /* send it using send_frame */
331 rc = efct_sframe_send_fcp_rsp(node, seq, rsp: &fcprsp, rsp_len: sizeof(fcprsp));
332 if (rc)
333 efc_log_debug(efct, "efct_sframe_send_fcp_rsp failed %d\n", rc);
334
335 return rc;
336}
337
338int
339efct_dispatch_fcp_cmd(struct efct_node *node, struct efc_hw_sequence *seq)
340{
341 struct efct *efct = node->efct;
342 struct fc_frame_header *fchdr = seq->header->dma.virt;
343 struct fcp_cmnd *cmnd = NULL;
344 struct efct_io *io = NULL;
345 u32 lun;
346
347 if (!seq->payload) {
348 efc_log_err(efct, "Sequence payload is NULL.\n");
349 return -EIO;
350 }
351
352 cmnd = seq->payload->dma.virt;
353
354 /* perform FCP_CMND validation check(s) */
355 if (efct_validate_fcp_cmd(efct, seq))
356 return -EIO;
357
358 lun = scsilun_to_int(&cmnd->fc_lun);
359 if (lun == U32_MAX)
360 return -EIO;
361
362 io = efct_scsi_io_alloc(node);
363 if (!io) {
364 int rc;
365
366 /* Use SEND_FRAME to send task set full or busy */
367 rc = efct_sframe_send_task_set_full_or_busy(node, seq);
368 if (rc)
369 efc_log_err(efct, "Failed to send busy task: %d\n", rc);
370
371 return rc;
372 }
373
374 io->hw_priv = seq->hw_priv;
375
376 io->app_id = 0;
377
378 /* RQ pair, if we got here, SIT=1 */
379 efct_populate_io_fcp_cmd(io, cmnd, fchdr, sit: true);
380
381 if (cmnd->fc_tm_flags) {
382 efct_dispatch_unsol_tmf(io, tm_flags: cmnd->fc_tm_flags, lun);
383 } else {
384 u32 flags = efct_get_flags_fcp_cmd(cmnd);
385
386 if (cmnd->fc_flags & FCP_CFL_LEN_MASK) {
387 efc_log_err(efct, "Additional CDB not supported\n");
388 return -EIO;
389 }
390 /*
391 * Can return failure for things like task set full and UAs,
392 * no need to treat as a dropped frame if rc != 0
393 */
394 efct_scsi_recv_cmd(io, lun, cdb: cmnd->fc_cdb,
395 cdb_len: sizeof(cmnd->fc_cdb), flags);
396 }
397
398 return 0;
399}
400
401static int
402efct_process_abts(struct efct_io *io, struct fc_frame_header *hdr)
403{
404 struct efct_node *node = io->node;
405 struct efct *efct = io->efct;
406 u16 ox_id = be16_to_cpu(hdr->fh_ox_id);
407 u16 rx_id = be16_to_cpu(hdr->fh_rx_id);
408 struct efct_io *abortio;
409
410 /* Find IO and attempt to take a reference on it */
411 abortio = efct_io_find_tgt_io(efct, node, ox_id, rx_id);
412
413 if (abortio) {
414 /* Got a reference on the IO. Hold it until backend
415 * is notified below
416 */
417 efc_log_info(node->efct, "Abort ox_id [%04x] rx_id [%04x]\n",
418 ox_id, rx_id);
419
420 /*
421 * Save the ox_id for the ABTS as the init_task_tag in our
422 * manufactured
423 * TMF IO object
424 */
425 io->display_name = "abts";
426 io->init_task_tag = ox_id;
427 /* don't set tgt_task_tag, don't want to confuse with XRI */
428
429 /*
430 * Save the rx_id from the ABTS as it is
431 * needed for the BLS response,
432 * regardless of the IO context's rx_id
433 */
434 io->abort_rx_id = rx_id;
435
436 /* Call target server command abort */
437 io->tmf_cmd = EFCT_SCSI_TMF_ABORT_TASK;
438 efct_scsi_recv_tmf(tmfio: io, lun: abortio->tgt_io.lun,
439 cmd: EFCT_SCSI_TMF_ABORT_TASK, abortio, flags: 0);
440
441 /*
442 * Backend will have taken an additional
443 * reference on the IO if needed;
444 * done with current reference.
445 */
446 kref_put(kref: &abortio->ref, release: abortio->release);
447 } else {
448 /*
449 * Either IO was not found or it has been
450 * freed between finding it
451 * and attempting to get the reference,
452 */
453 efc_log_info(node->efct, "Abort: ox_id [%04x], IO not found\n",
454 ox_id);
455
456 /* Send a BA_RJT */
457 efct_bls_send_rjt(io, hdr);
458 }
459 return 0;
460}
461
462int
463efct_node_recv_abts_frame(struct efct_node *node, struct efc_hw_sequence *seq)
464{
465 struct efct *efct = node->efct;
466 struct fc_frame_header *hdr = seq->header->dma.virt;
467 struct efct_io *io = NULL;
468
469 node->abort_cnt++;
470 io = efct_scsi_io_alloc(node);
471 if (io) {
472 io->hw_priv = seq->hw_priv;
473 /* If we got this far, SIT=1 */
474 io->seq_init = 1;
475
476 /* fill out generic fields */
477 io->efct = efct;
478 io->node = node;
479 io->cmd_tgt = true;
480
481 efct_process_abts(io, hdr: seq->header->dma.virt);
482 } else {
483 efc_log_err(efct,
484 "SCSI IO allocation failed for ABTS received ");
485 efc_log_err(efct, "s_id %06x d_id %06x ox_id %04x rx_id %04x\n",
486 ntoh24(hdr->fh_s_id), ntoh24(hdr->fh_d_id),
487 be16_to_cpu(hdr->fh_ox_id),
488 be16_to_cpu(hdr->fh_rx_id));
489 }
490
491 return 0;
492}
493

source code of linux/drivers/scsi/elx/efct/efct_unsol.c