1/*-
2 * Copyright (c) 2017 Broadcom. All rights reserved.
3 * The term "Broadcom" refers to Broadcom Limited and/or its subsidiaries.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright notice,
9 *    this list of conditions and the following disclaimer.
10 *
11 * 2. Redistributions in binary form must reproduce the above copyright notice,
12 *    this list of conditions and the following disclaimer in the documentation
13 *    and/or other materials provided with the distribution.
14 *
15 * 3. Neither the name of the copyright holder nor the names of its contributors
16 *    may be used to endorse or promote products derived from this software
17 *    without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
23 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
30 *
31 * $FreeBSD$
32 */
33
34/**
35 * @file
36 * Code to handle unsolicited received FC frames.
37 */
38
39/*!
40 * @defgroup unsol Unsolicited Frame Handling
41 */
42
43#include "ocs.h"
44#include "ocs_els.h"
45#include "ocs_fabric.h"
46#include "ocs_device.h"
47
48
49#define frame_printf(ocs, hdr, fmt, ...) \
50	do { \
51		char s_id_text[16]; \
52		ocs_node_fcid_display(fc_be24toh((hdr)->s_id), s_id_text, sizeof(s_id_text)); \
53		ocs_log_debug(ocs, "[%06x.%s] %02x/%04x/%04x: " fmt, fc_be24toh((hdr)->d_id), s_id_text, \
54			(hdr)->r_ctl, ocs_be16toh((hdr)->ox_id), ocs_be16toh((hdr)->rx_id), ##__VA_ARGS__); \
55	} while(0)
56
57static int32_t ocs_unsol_process(ocs_t *ocs, ocs_hw_sequence_t *seq);
58static int32_t ocs_dispatch_fcp_cmd(ocs_node_t *node, ocs_hw_sequence_t *seq);
59static int32_t ocs_dispatch_fcp_cmd_auto_xfer_rdy(ocs_node_t *node, ocs_hw_sequence_t *seq);
60static int32_t ocs_dispatch_fcp_data(ocs_node_t *node, ocs_hw_sequence_t *seq);
61static int32_t ocs_domain_dispatch_frame(void *arg, ocs_hw_sequence_t *seq);
62static int32_t ocs_node_dispatch_frame(void *arg, ocs_hw_sequence_t *seq);
63static int32_t ocs_fc_tmf_rejected_cb(ocs_io_t *io, ocs_scsi_io_status_e scsi_status, uint32_t flags, void *arg);
64static ocs_hw_sequence_t *ocs_frame_next(ocs_list_t *pend_list, ocs_lock_t *list_lock);
65static uint8_t ocs_node_frames_held(void *arg);
66static uint8_t ocs_domain_frames_held(void *arg);
67static int32_t ocs_purge_pending(ocs_t *ocs, ocs_list_t *pend_list, ocs_lock_t *list_lock);
68static int32_t ocs_sframe_send_task_set_full_or_busy(ocs_node_t *node, ocs_hw_sequence_t *seq);
69
70#define OCS_MAX_FRAMES_BEFORE_YEILDING 10000
71
72/**
73 * @brief Process the RQ circular buffer and process the incoming frames.
74 *
75 * @param mythread Pointer to thread object.
76 *
77 * @return Returns 0 on success, or a non-zero value on failure.
78 */
79int32_t
80ocs_unsol_rq_thread(ocs_thread_t *mythread)
81{
82	ocs_xport_rq_thread_info_t *thread_data = mythread->arg;
83	ocs_t *ocs = thread_data->ocs;
84	ocs_hw_sequence_t *seq;
85	uint32_t yield_count = OCS_MAX_FRAMES_BEFORE_YEILDING;
86
87	ocs_log_debug(ocs, "%s running\n", mythread->name);
88	while (!ocs_thread_terminate_requested(mythread)) {
89		seq = ocs_cbuf_get(thread_data->seq_cbuf, 100000);
90		if (seq == NULL) {
91			/* Prevent soft lockups by yielding the CPU */
92			ocs_thread_yield(&thread_data->thread);
93			yield_count = OCS_MAX_FRAMES_BEFORE_YEILDING;
94			continue;
95		}
96		/* Note: Always returns 0 */
97		ocs_unsol_process((ocs_t*)seq->hw->os, seq);
98
99		/* We have to prevent CPU soft lockups, so just yield the CPU after x frames. */
100		if (--yield_count == 0) {
101			ocs_thread_yield(&thread_data->thread);
102			yield_count = OCS_MAX_FRAMES_BEFORE_YEILDING;
103		}
104	}
105	ocs_log_debug(ocs, "%s exiting\n", mythread->name);
106	thread_data->thread_started = FALSE;
107	return 0;
108}
109
110/**
111 * @ingroup unsol
112 * @brief Callback function when aborting a port owned XRI
113 * exchanges.
114 *
115 * @return Returns 0.
116 */
117static int32_t
118ocs_unsol_abort_cb (ocs_hw_io_t *hio, ocs_remote_node_t *rnode, uint32_t len, int32_t status, uint32_t ext, void *arg)
119{
120	ocs_t *ocs = arg;
121	ocs_assert(hio, -1);
122	ocs_assert(arg, -1);
123	ocs_log_debug(ocs, "xri=0x%x tag=0x%x\n", hio->indicator, hio->reqtag);
124	ocs_hw_io_free(&ocs->hw, hio);
125	return 0;
126}
127
128
129/**
130 * @ingroup unsol
131 * @brief Abort either a RQ Pair auto XFER RDY XRI.
132 * @return Returns None.
133 */
134static void
135ocs_port_owned_abort(ocs_t *ocs, ocs_hw_io_t *hio)
136{
137	ocs_hw_rtn_e hw_rc;
138	hw_rc = ocs_hw_io_abort(&ocs->hw, hio, FALSE,
139				  ocs_unsol_abort_cb, ocs);
140	if((hw_rc == OCS_HW_RTN_IO_ABORT_IN_PROGRESS) ||
141	   (hw_rc == OCS_HW_RTN_IO_PORT_OWNED_ALREADY_ABORTED)) {
142		ocs_log_debug(ocs, "already aborted XRI 0x%x\n", hio->indicator);
143	} else if(hw_rc != OCS_HW_RTN_SUCCESS) {
144		ocs_log_debug(ocs, "Error aborting XRI 0x%x status %d\n",
145			      hio->indicator, hw_rc);
146	}
147}
148
149/**
150 * @ingroup unsol
151 * @brief Handle unsolicited FC frames.
152 *
153 * <h3 class="desc">Description</h3>
154 * This function is called from the HW with unsolicited FC frames (FCP, ELS, BLS, etc.).
155 *
156 * @param arg Application-specified callback data.
157 * @param seq Header/payload sequence buffers.
158 *
159 * @return Returns 0 on success; or a negative error value on failure.
160 */
161
162int32_t
163ocs_unsolicited_cb(void *arg, ocs_hw_sequence_t *seq)
164{
165	ocs_t *ocs = arg;
166	ocs_xport_t *xport = ocs->xport;
167	int32_t rc;
168
169	CPUTRACE("");
170
171	if (ocs->rq_threads == 0) {
172		rc = ocs_unsol_process(ocs, seq);
173	} else {
174		/* use the ox_id to dispatch this IO to a thread */
175		fc_header_t *hdr = seq->header->dma.virt;
176		uint32_t ox_id =  ocs_be16toh(hdr->ox_id);
177		uint32_t thr_index = ox_id % ocs->rq_threads;
178
179		rc = ocs_cbuf_put(xport->rq_thread_info[thr_index].seq_cbuf, seq);
180	}
181
182	if (rc) {
183		ocs_hw_sequence_free(&ocs->hw, seq);
184	}
185
186	return 0;
187}
188
189/**
190 * @ingroup unsol
191 * @brief Handle unsolicited FC frames.
192 *
193 * <h3 class="desc">Description</h3>
194 * This function is called either from ocs_unsolicited_cb() or ocs_unsol_rq_thread().
195 *
196 * @param ocs Pointer to the ocs structure.
197 * @param seq Header/payload sequence buffers.
198 *
199 * @return Returns 0 on success, or a negative error value on failure.
200 */
201static int32_t
202ocs_unsol_process(ocs_t *ocs, ocs_hw_sequence_t *seq)
203{
204	ocs_xport_fcfi_t *xport_fcfi = NULL;
205	ocs_domain_t *domain;
206	uint8_t seq_fcfi = seq->fcfi;
207
208	/* HW_WORKAROUND_OVERRIDE_FCFI_IN_SRB */
209	if (ocs->hw.workaround.override_fcfi) {
210		if (ocs->hw.first_domain_idx > -1) {
211			seq_fcfi = ocs->hw.first_domain_idx;
212		}
213	}
214
215	/* Range check seq->fcfi */
216	if (seq_fcfi < ARRAY_SIZE(ocs->xport->fcfi)) {
217		xport_fcfi = &ocs->xport->fcfi[seq_fcfi];
218	}
219
220	/* If the transport FCFI entry is NULL, then drop the frame */
221	if (xport_fcfi == NULL) {
222		ocs_log_test(ocs, "FCFI %d is not valid, dropping frame\n", seq->fcfi);
223		if (seq->hio != NULL) {
224			ocs_port_owned_abort(ocs, seq->hio);
225		}
226
227		ocs_hw_sequence_free(&ocs->hw, seq);
228		return 0;
229	}
230	domain = ocs_hw_domain_get(&ocs->hw, seq_fcfi);
231
232	/*
233	 * If we are holding frames or the domain is not yet registered or
234	 * there's already frames on the pending list,
235	 * then add the new frame to pending list
236	 */
237	if (domain == NULL ||
238	    xport_fcfi->hold_frames ||
239	    !ocs_list_empty(&xport_fcfi->pend_frames)) {
240		ocs_lock(&xport_fcfi->pend_frames_lock);
241			ocs_list_add_tail(&xport_fcfi->pend_frames, seq);
242		ocs_unlock(&xport_fcfi->pend_frames_lock);
243
244		if (domain != NULL) {
245			/* immediately process pending frames */
246			ocs_domain_process_pending(domain);
247		}
248	} else {
249		/*
250		 * We are not holding frames and pending list is empty, just process frame.
251		 * A non-zero return means the frame was not handled - so cleanup
252		 */
253		if (ocs_domain_dispatch_frame(domain, seq)) {
254			if (seq->hio != NULL) {
255				ocs_port_owned_abort(ocs, seq->hio);
256			}
257			ocs_hw_sequence_free(&ocs->hw, seq);
258		}
259	}
260	return 0;
261}
262
263/**
264 * @ingroup unsol
265 * @brief Process pending frames queued to the given node.
266 *
267 * <h3 class="desc">Description</h3>
268 * Frames that are queued for the \c node are dispatched and returned
269 * to the RQ.
270 *
271 * @param node Node of the queued frames that are to be dispatched.
272 *
273 * @return Returns 0 on success, or a negative error value on failure.
274 */
275
276int32_t
277ocs_process_node_pending(ocs_node_t *node)
278{
279	ocs_t *ocs = node->ocs;
280	ocs_hw_sequence_t *seq = NULL;
281	uint32_t pend_frames_processed = 0;
282
283	for (;;) {
284		/* need to check for hold frames condition after each frame processed
285		 * because any given frame could cause a transition to a state that
286		 * holds frames
287		 */
288		if (ocs_node_frames_held(node)) {
289			break;
290		}
291
292		/* Get next frame/sequence */
293		ocs_lock(&node->pend_frames_lock);
294			seq = ocs_list_remove_head(&node->pend_frames);
295			if (seq == NULL) {
296				pend_frames_processed = node->pend_frames_processed;
297				node->pend_frames_processed = 0;
298				ocs_unlock(&node->pend_frames_lock);
299				break;
300			}
301			node->pend_frames_processed++;
302		ocs_unlock(&node->pend_frames_lock);
303
304		/* now dispatch frame(s) to dispatch function */
305		if (ocs_node_dispatch_frame(node, seq)) {
306			if (seq->hio != NULL) {
307				ocs_port_owned_abort(ocs, seq->hio);
308			}
309			ocs_hw_sequence_free(&ocs->hw, seq);
310		}
311	}
312
313	if (pend_frames_processed != 0) {
314		ocs_log_debug(ocs, "%u node frames held and processed\n", pend_frames_processed);
315	}
316
317	return 0;
318}
319
320/**
321 * @ingroup unsol
322 * @brief Process pending frames queued to the given domain.
323 *
324 * <h3 class="desc">Description</h3>
325 * Frames that are queued for the \c domain are dispatched and
326 * returned to the RQ.
327 *
328 * @param domain Domain of the queued frames that are to be
329 *		 dispatched.
330 *
331 * @return Returns 0 on success, or a negative error value on failure.
332 */
333
334int32_t
335ocs_domain_process_pending(ocs_domain_t *domain)
336{
337	ocs_t *ocs = domain->ocs;
338	ocs_xport_fcfi_t *xport_fcfi;
339	ocs_hw_sequence_t *seq = NULL;
340	uint32_t pend_frames_processed = 0;
341
342	ocs_assert(domain->fcf_indicator < SLI4_MAX_FCFI, -1);
343	xport_fcfi = &ocs->xport->fcfi[domain->fcf_indicator];
344
345	for (;;) {
346		/* need to check for hold frames condition after each frame processed
347		 * because any given frame could cause a transition to a state that
348		 * holds frames
349		 */
350		if (ocs_domain_frames_held(domain)) {
351			break;
352		}
353
354		/* Get next frame/sequence */
355		ocs_lock(&xport_fcfi->pend_frames_lock);
356			seq = ocs_list_remove_head(&xport_fcfi->pend_frames);
357			if (seq == NULL) {
358				pend_frames_processed = xport_fcfi->pend_frames_processed;
359				xport_fcfi->pend_frames_processed = 0;
360				ocs_unlock(&xport_fcfi->pend_frames_lock);
361				break;
362			}
363			xport_fcfi->pend_frames_processed++;
364		ocs_unlock(&xport_fcfi->pend_frames_lock);
365
366		/* now dispatch frame(s) to dispatch function */
367		if (ocs_domain_dispatch_frame(domain, seq)) {
368			if (seq->hio != NULL) {
369				ocs_port_owned_abort(ocs, seq->hio);
370			}
371			ocs_hw_sequence_free(&ocs->hw, seq);
372		}
373	}
374	if (pend_frames_processed != 0) {
375		ocs_log_debug(ocs, "%u domain frames held and processed\n", pend_frames_processed);
376	}
377	return 0;
378}
379
380/**
381 * @ingroup unsol
382 * @brief Purge given pending list
383 *
384 * <h3 class="desc">Description</h3>
385 * Frames that are queued on the given pending list are
386 * discarded and returned to the RQ.
387 *
388 * @param ocs Pointer to ocs object.
389 * @param pend_list Pending list to be purged.
390 * @param list_lock Lock that protects pending list.
391 *
392 * @return Returns 0 on success, or a negative error value on failure.
393 */
394
395static int32_t
396ocs_purge_pending(ocs_t *ocs, ocs_list_t *pend_list, ocs_lock_t *list_lock)
397{
398	ocs_hw_sequence_t *frame;
399
400	for (;;) {
401		frame = ocs_frame_next(pend_list, list_lock);
402		if (frame == NULL) {
403			break;
404		}
405
406		frame_printf(ocs, (fc_header_t*) frame->header->dma.virt, "Discarding held frame\n");
407		if (frame->hio != NULL) {
408			ocs_port_owned_abort(ocs, frame->hio);
409		}
410		ocs_hw_sequence_free(&ocs->hw, frame);
411	}
412
413	return 0;
414}
415
416/**
417 * @ingroup unsol
418 * @brief Purge node's pending (queued) frames.
419 *
420 * <h3 class="desc">Description</h3>
421 * Frames that are queued for the \c node are discarded and returned
422 * to the RQ.
423 *
424 * @param node Node of the queued frames that are to be discarded.
425 *
426 * @return Returns 0 on success, or a negative error value on failure.
427 */
428
429int32_t
430ocs_node_purge_pending(ocs_node_t *node)
431{
432	return ocs_purge_pending(node->ocs, &node->pend_frames, &node->pend_frames_lock);
433}
434
435/**
436 * @ingroup unsol
437 * @brief Purge xport's pending (queued) frames.
438 *
439 * <h3 class="desc">Description</h3>
440 * Frames that are queued for the \c xport are discarded and
441 * returned to the RQ.
442 *
443 * @param domain Pointer to domain object.
444 *
445 * @return Returns 0 on success; or a negative error value on failure.
446 */
447
448int32_t
449ocs_domain_purge_pending(ocs_domain_t *domain)
450{
451	ocs_t *ocs = domain->ocs;
452	ocs_xport_fcfi_t *xport_fcfi;
453
454	ocs_assert(domain->fcf_indicator < SLI4_MAX_FCFI, -1);
455	xport_fcfi = &ocs->xport->fcfi[domain->fcf_indicator];
456	return ocs_purge_pending(domain->ocs,
457				 &xport_fcfi->pend_frames,
458				 &xport_fcfi->pend_frames_lock);
459}
460
461/**
462 * @ingroup unsol
463 * @brief Check if node's pending frames are held.
464 *
465 * @param arg Node for which the pending frame hold condition is
466 * checked.
467 *
468 * @return Returns 1 if node is holding pending frames, or 0
469 * if not.
470 */
471
472static uint8_t
473ocs_node_frames_held(void *arg)
474{
475	ocs_node_t *node = (ocs_node_t *)arg;
476	return node->hold_frames;
477}
478
479/**
480 * @ingroup unsol
481 * @brief Check if domain's pending frames are held.
482 *
483 * @param arg Domain for which the pending frame hold condition is
484 * checked.
485 *
486 * @return Returns 1 if domain is holding pending frames, or 0
487 * if not.
488 */
489
490static uint8_t
491ocs_domain_frames_held(void *arg)
492{
493	ocs_domain_t *domain = (ocs_domain_t *)arg;
494	ocs_t *ocs = domain->ocs;
495	ocs_xport_fcfi_t *xport_fcfi;
496
497	ocs_assert(domain != NULL, 1);
498	ocs_assert(domain->fcf_indicator < SLI4_MAX_FCFI, 1);
499	xport_fcfi = &ocs->xport->fcfi[domain->fcf_indicator];
500	return xport_fcfi->hold_frames;
501}
502
503/**
504 * @ingroup unsol
505 * @brief Globally (at xport level) hold unsolicited frames.
506 *
507 * <h3 class="desc">Description</h3>
508 * This function places a hold on processing unsolicited FC
509 * frames queued to the xport pending list.
510 *
511 * @param domain Pointer to domain object.
512 *
513 * @return Returns None.
514 */
515
516void
517ocs_domain_hold_frames(ocs_domain_t *domain)
518{
519	ocs_t *ocs = domain->ocs;
520	ocs_xport_fcfi_t *xport_fcfi;
521
522	ocs_assert(domain->fcf_indicator < SLI4_MAX_FCFI);
523	xport_fcfi = &ocs->xport->fcfi[domain->fcf_indicator];
524	if (!xport_fcfi->hold_frames) {
525		ocs_log_debug(domain->ocs, "hold frames set for FCFI %d\n",
526			      domain->fcf_indicator);
527		xport_fcfi->hold_frames = 1;
528	}
529}
530
531/**
532 * @ingroup unsol
533 * @brief Clear hold on unsolicited frames.
534 *
535 * <h3 class="desc">Description</h3>
536 * This function clears the hold on processing unsolicited FC
537 * frames queued to the domain pending list.
538 *
539 * @param domain Pointer to domain object.
540 *
541 * @return Returns None.
542 */
543
544void
545ocs_domain_accept_frames(ocs_domain_t *domain)
546{
547	ocs_t *ocs = domain->ocs;
548	ocs_xport_fcfi_t *xport_fcfi;
549
550	ocs_assert(domain->fcf_indicator < SLI4_MAX_FCFI);
551	xport_fcfi = &ocs->xport->fcfi[domain->fcf_indicator];
552	if (xport_fcfi->hold_frames == 1) {
553		ocs_log_debug(domain->ocs, "hold frames cleared for FCFI %d\n",
554			      domain->fcf_indicator);
555	}
556	xport_fcfi->hold_frames = 0;
557	ocs_domain_process_pending(domain);
558}
559
560
561/**
562 * @ingroup unsol
563 * @brief Dispatch unsolicited FC frame.
564 *
565 * <h3 class="desc">Description</h3>
566 * This function processes an unsolicited FC frame queued at the
567 * domain level.
568 *
569 * @param arg Pointer to ocs object.
570 * @param seq Header/payload sequence buffers.
571 *
572 * @return Returns 0 if frame processed and RX buffers cleaned
573 * up appropriately, -1 if frame not handled.
574 */
575
576static __inline int32_t
577ocs_domain_dispatch_frame(void *arg, ocs_hw_sequence_t *seq)
578{
579	ocs_domain_t *domain = (ocs_domain_t *)arg;
580	ocs_t *ocs = domain->ocs;
581	fc_header_t *hdr;
582	uint32_t s_id;
583	uint32_t d_id;
584	ocs_node_t *node = NULL;
585	ocs_sport_t *sport = NULL;
586
587	ocs_assert(seq->header, -1);
588	ocs_assert(seq->header->dma.virt, -1);
589	ocs_assert(seq->payload->dma.virt, -1);
590
591	hdr = seq->header->dma.virt;
592
593	/* extract the s_id and d_id */
594	s_id = fc_be24toh(hdr->s_id);
595	d_id = fc_be24toh(hdr->d_id);
596
597	sport = domain->sport;
598	if (sport == NULL) {
599		frame_printf(ocs, hdr, "phy sport for FC ID 0x%06x is NULL, dropping frame\n", d_id);
600		return -1;
601	}
602
603	if (sport->fc_id != d_id) {
604		/* Not a physical port IO lookup sport associated with the npiv port */
605		sport = ocs_sport_find(domain, d_id); /* Look up without lock */
606		if (sport == NULL) {
607			if (hdr->type == FC_TYPE_FCP) {
608				/* Drop frame */
609				ocs_log_warn(ocs, "unsolicited FCP frame with invalid d_id x%x, dropping\n",
610					     d_id);
611				return -1;
612			} else {
613				/* p2p will use this case */
614				sport = domain->sport;
615			}
616		}
617	}
618
619	/* Lookup the node given the remote s_id */
620	node = ocs_node_find(sport, s_id);
621
622	/* If not found, then create a new node */
623	if (node == NULL) {
624		/* If this is solicited data or control based on R_CTL and there is no node context,
625		 * then we can drop the frame
626		 */
627		if ((hdr->r_ctl == FC_RCTL_FC4_DATA) && (
628		    (hdr->info == FC_RCTL_INFO_SOL_DATA) || (hdr->info == FC_RCTL_INFO_SOL_CTRL))) {
629			ocs_log_debug(ocs, "solicited data/ctrl frame without node, dropping\n");
630			return -1;
631		}
632		node = ocs_node_alloc(sport, s_id, FALSE, FALSE);
633		if (node == NULL) {
634			ocs_log_err(ocs, "ocs_node_alloc() failed\n");
635			return -1;
636		}
637		/* don't send PLOGI on ocs_d_init entry */
638		ocs_node_init_device(node, FALSE);
639	}
640
641	if (node->hold_frames || !ocs_list_empty((&node->pend_frames))) {
642		/* TODO: info log level
643		frame_printf(ocs, hdr, "Holding frame\n");
644		*/
645		/* add frame to node's pending list */
646		ocs_lock(&node->pend_frames_lock);
647			ocs_list_add_tail(&node->pend_frames, seq);
648		ocs_unlock(&node->pend_frames_lock);
649
650		return 0;
651	}
652
653	/* now dispatch frame to the node frame handler */
654	return ocs_node_dispatch_frame(node, seq);
655}
656
657/**
658 * @ingroup unsol
659 * @brief Dispatch a frame.
660 *
661 * <h3 class="desc">Description</h3>
662 * A frame is dispatched from the \c node to the handler.
663 *
664 * @param arg Node that originated the frame.
665 * @param seq Header/payload sequence buffers.
666 *
667 * @return Returns 0 if frame processed and RX buffers cleaned
668 * up appropriately, -1 if frame not handled.
669 */
670static int32_t
671ocs_node_dispatch_frame(void *arg, ocs_hw_sequence_t *seq)
672{
673
674	fc_header_t *hdr = seq->header->dma.virt;
675	uint32_t port_id;
676	ocs_node_t *node = (ocs_node_t *)arg;
677	int32_t rc = -1;
678	int32_t sit_set = 0;
679
680	port_id = fc_be24toh(hdr->s_id);
681	ocs_assert(port_id == node->rnode.fc_id, -1);
682
683	if (fc_be24toh(hdr->f_ctl) & FC_FCTL_END_SEQUENCE) {
684		/*if SIT is set */
685		if (fc_be24toh(hdr->f_ctl) & FC_FCTL_SEQUENCE_INITIATIVE) {
686			sit_set = 1;
687		}
688		switch (hdr->r_ctl) {
689		case FC_RCTL_ELS:
690			if (sit_set) {
691				rc = ocs_node_recv_els_frame(node, seq);
692			}
693			break;
694
695		case FC_RCTL_BLS:
696			if (sit_set) {
697				rc = ocs_node_recv_abts_frame(node, seq);
698			}else {
699				rc = ocs_node_recv_bls_no_sit(node, seq);
700			}
701			break;
702
703		case FC_RCTL_FC4_DATA:
704			switch(hdr->type) {
705			case FC_TYPE_FCP:
706				if (hdr->info == FC_RCTL_INFO_UNSOL_CMD) {
707					if (node->fcp_enabled) {
708						if (sit_set) {
709							rc = ocs_dispatch_fcp_cmd(node, seq);
710						}else {
711							/* send the auto xfer ready command */
712							rc = ocs_dispatch_fcp_cmd_auto_xfer_rdy(node, seq);
713						}
714					} else {
715						rc = ocs_node_recv_fcp_cmd(node, seq);
716					}
717				} else if (hdr->info == FC_RCTL_INFO_SOL_DATA) {
718					if (sit_set) {
719						rc = ocs_dispatch_fcp_data(node, seq);
720					}
721				}
722				break;
723			case FC_TYPE_GS:
724				if (sit_set) {
725					rc = ocs_node_recv_ct_frame(node, seq);
726				}
727				break;
728			default:
729				break;
730			}
731			break;
732		}
733	} else {
734		node_printf(node, "Dropping frame hdr = %08x %08x %08x %08x %08x %08x\n",
735			    ocs_htobe32(((uint32_t *)hdr)[0]),
736			    ocs_htobe32(((uint32_t *)hdr)[1]),
737			    ocs_htobe32(((uint32_t *)hdr)[2]),
738			    ocs_htobe32(((uint32_t *)hdr)[3]),
739			    ocs_htobe32(((uint32_t *)hdr)[4]),
740			    ocs_htobe32(((uint32_t *)hdr)[5]));
741	}
742	return rc;
743}
744
745/**
746 * @ingroup unsol
747 * @brief Dispatch unsolicited FCP frames (RQ Pair).
748 *
749 * <h3 class="desc">Description</h3>
750 * Dispatch unsolicited FCP frames (called from the device node state machine).
751 *
752 * @param io Pointer to the IO context.
753 * @param task_management_flags Task management flags from the FCP_CMND frame.
754 * @param node Node that originated the frame.
755 * @param lun 32-bit LUN from FCP_CMND frame.
756 *
757 * @return Returns None.
758 */
759
760static void
761ocs_dispatch_unsolicited_tmf(ocs_io_t *io, uint8_t task_management_flags, ocs_node_t *node, uint64_t lun)
762{
763	uint32_t i;
764	struct {
765		uint32_t mask;
766		ocs_scsi_tmf_cmd_e cmd;
767	} tmflist[] = {
768		{FCP_QUERY_TASK_SET,		OCS_SCSI_TMF_QUERY_TASK_SET},
769		{FCP_ABORT_TASK_SET,		OCS_SCSI_TMF_ABORT_TASK_SET},
770		{FCP_CLEAR_TASK_SET,		OCS_SCSI_TMF_CLEAR_TASK_SET},
771		{FCP_QUERY_ASYNCHRONOUS_EVENT,	OCS_SCSI_TMF_QUERY_ASYNCHRONOUS_EVENT},
772		{FCP_LOGICAL_UNIT_RESET,	OCS_SCSI_TMF_LOGICAL_UNIT_RESET},
773		{FCP_TARGET_RESET,		OCS_SCSI_TMF_TARGET_RESET},
774		{FCP_CLEAR_ACA,			OCS_SCSI_TMF_CLEAR_ACA}};
775
776	io->exp_xfer_len = 0; /* BUG 32235 */
777
778	for (i = 0; i < ARRAY_SIZE(tmflist); i ++) {
779		if (tmflist[i].mask & task_management_flags) {
780			io->tmf_cmd = tmflist[i].cmd;
781			ocs_scsi_recv_tmf(io, lun, tmflist[i].cmd, NULL, 0);
782			break;
783		}
784	}
785	if (i == ARRAY_SIZE(tmflist)) {
786		/* Not handled */
787		node_printf(node, "TMF x%x rejected\n", task_management_flags);
788		ocs_scsi_send_tmf_resp(io, OCS_SCSI_TMF_FUNCTION_REJECTED, NULL, ocs_fc_tmf_rejected_cb, NULL);
789	}
790}
791
792static int32_t
793ocs_validate_fcp_cmd(ocs_t *ocs, ocs_hw_sequence_t *seq)
794{
795	size_t		exp_payload_len = 0;
796	fcp_cmnd_iu_t *cmnd = seq->payload->dma.virt;
797	exp_payload_len = sizeof(fcp_cmnd_iu_t) - 16 + cmnd->additional_fcp_cdb_length;
798
799	/*
800	 * If we received less than FCP_CMND_IU bytes, assume that the frame is
801	 * corrupted in some way and drop it. This was seen when jamming the FCTL
802	 * fill bytes field.
803	 */
804	if (seq->payload->dma.len < exp_payload_len) {
805		fc_header_t	*fchdr = seq->header->dma.virt;
806		ocs_log_debug(ocs, "dropping ox_id %04x with payload length (%zd) less than expected (%zd)\n",
807			      ocs_be16toh(fchdr->ox_id), seq->payload->dma.len,
808			      exp_payload_len);
809		return -1;
810	}
811	return 0;
812
813}
814
815static void
816ocs_populate_io_fcp_cmd(ocs_io_t *io, fcp_cmnd_iu_t *cmnd, fc_header_t *fchdr, uint8_t sit)
817{
818	uint32_t	*fcp_dl;
819	io->init_task_tag = ocs_be16toh(fchdr->ox_id);
820	/* note, tgt_task_tag, hw_tag  set when HW io is allocated */
821	fcp_dl = (uint32_t*)(&(cmnd->fcp_cdb_and_dl));
822	fcp_dl += cmnd->additional_fcp_cdb_length;
823	io->exp_xfer_len = ocs_be32toh(*fcp_dl);
824	io->transferred = 0;
825
826	/* The upper 7 bits of CS_CTL is the frame priority thru the SAN.
827	 * Our assertion here is, the priority given to a frame containing
828	 * the FCP cmd should be the priority given to ALL frames contained
829	 * in that IO. Thus we need to save the incoming CS_CTL here.
830	 */
831	if (fc_be24toh(fchdr->f_ctl) & FC_FCTL_PRIORITY_ENABLE) {
832		io->cs_ctl = fchdr->cs_ctl;
833	} else {
834		io->cs_ctl = 0;
835	}
836	io->seq_init = sit;
837}
838
839static uint32_t
840ocs_get_flags_fcp_cmd(fcp_cmnd_iu_t *cmnd)
841{
842	uint32_t flags = 0;
843	switch (cmnd->task_attribute) {
844	case FCP_TASK_ATTR_SIMPLE:
845		flags |= OCS_SCSI_CMD_SIMPLE;
846		break;
847	case FCP_TASK_ATTR_HEAD_OF_QUEUE:
848		flags |= OCS_SCSI_CMD_HEAD_OF_QUEUE;
849		break;
850	case FCP_TASK_ATTR_ORDERED:
851		flags |= OCS_SCSI_CMD_ORDERED;
852		break;
853	case FCP_TASK_ATTR_ACA:
854		flags |= OCS_SCSI_CMD_ACA;
855		break;
856	case FCP_TASK_ATTR_UNTAGGED:
857		flags |= OCS_SCSI_CMD_UNTAGGED;
858		break;
859	}
860	flags |= (uint32_t)cmnd->command_priority << OCS_SCSI_PRIORITY_SHIFT;
861	if (cmnd->wrdata)
862		flags |= OCS_SCSI_CMD_DIR_IN;
863	if (cmnd->rddata)
864		flags |= OCS_SCSI_CMD_DIR_OUT;
865
866	return flags;
867}
868
869/**
870 * @ingroup unsol
871 * @brief Dispatch unsolicited FCP_CMND frame.
872 *
873 * <h3 class="desc">Description</h3>
874 * Dispatch unsolicited FCP_CMND frame. RQ Pair mode - always
875 * used for RQ Pair mode since first burst is not supported.
876 *
877 * @param node Node that originated the frame.
878 * @param seq Header/payload sequence buffers.
879 *
880 * @return Returns 0 if frame processed and RX buffers cleaned
881 * up appropriately, -1 if frame not handled and RX buffers need
882 * to be returned.
883 */
884static int32_t
885ocs_dispatch_fcp_cmd(ocs_node_t *node, ocs_hw_sequence_t *seq)
886{
887	ocs_t *ocs = node->ocs;
888	fc_header_t	*fchdr = seq->header->dma.virt;
889	fcp_cmnd_iu_t	*cmnd = NULL;
890	ocs_io_t	*io = NULL;
891	fc_vm_header_t 	*vhdr;
892	uint8_t 	df_ctl;
893	uint64_t	lun = UINT64_MAX;
894	int32_t		rc = 0;
895
896	ocs_assert(seq->payload, -1);
897	cmnd = seq->payload->dma.virt;
898
899	/* perform FCP_CMND validation check(s) */
900	if (ocs_validate_fcp_cmd(ocs, seq)) {
901		return -1;
902	}
903
904	lun = CAM_EXTLUN_BYTE_SWIZZLE(be64dec(cmnd->fcp_lun));
905	if (lun == UINT64_MAX) {
906		return -1;
907	}
908
909	io = ocs_scsi_io_alloc(node, OCS_SCSI_IO_ROLE_RESPONDER);
910	if (io == NULL) {
911		uint32_t send_frame_capable;
912
913		/* If we have SEND_FRAME capability, then use it to send task set full or busy */
914		rc = ocs_hw_get(&ocs->hw, OCS_HW_SEND_FRAME_CAPABLE, &send_frame_capable);
915		if ((rc == 0) && send_frame_capable) {
916			rc = ocs_sframe_send_task_set_full_or_busy(node, seq);
917			if (rc) {
918				ocs_log_test(ocs, "ocs_sframe_send_task_set_full_or_busy failed: %d\n", rc);
919			}
920			return rc;
921		}
922
923		ocs_log_err(ocs, "IO allocation failed ox_id %04x\n", ocs_be16toh(fchdr->ox_id));
924		return -1;
925	}
926	io->hw_priv = seq->hw_priv;
927
928	/* Check if the CMD has vmheader. */
929	io->app_id = 0;
930	df_ctl = fchdr->df_ctl;
931	if (df_ctl & FC_DFCTL_DEVICE_HDR_16_MASK) {
932		uint32_t vmhdr_offset = 0;
933		/* Presence of VMID. Get the vm header offset. */
934		if (df_ctl & FC_DFCTL_ESP_HDR_MASK) {
935			vmhdr_offset += FC_DFCTL_ESP_HDR_SIZE;
936			ocs_log_err(ocs, "ESP Header present. Fix ESP Size.\n");
937		}
938
939		if (df_ctl & FC_DFCTL_NETWORK_HDR_MASK) {
940			vmhdr_offset += FC_DFCTL_NETWORK_HDR_SIZE;
941		}
942		vhdr = (fc_vm_header_t *) ((char *)fchdr + sizeof(fc_header_t) + vmhdr_offset);
943		io->app_id = ocs_be32toh(vhdr->src_vmid);
944	}
945
946	/* RQ pair, if we got here, SIT=1 */
947	ocs_populate_io_fcp_cmd(io, cmnd, fchdr, TRUE);
948
949	if (cmnd->task_management_flags) {
950		ocs_dispatch_unsolicited_tmf(io, cmnd->task_management_flags, node, lun);
951	} else {
952		uint32_t flags = ocs_get_flags_fcp_cmd(cmnd);
953
954		/* can return failure for things like task set full and UAs,
955		 * no need to treat as a dropped frame if rc != 0
956		 */
957		ocs_scsi_recv_cmd(io, lun, cmnd->fcp_cdb,
958				  sizeof(cmnd->fcp_cdb) +
959				  (cmnd->additional_fcp_cdb_length * sizeof(uint32_t)),
960				  flags);
961	}
962
963	/* successfully processed, now return RX buffer to the chip */
964	ocs_hw_sequence_free(&ocs->hw, seq);
965	return 0;
966}
967
968/**
969 * @ingroup unsol
970 * @brief Dispatch unsolicited FCP_CMND frame (auto xfer rdy).
971 *
972 * <h3 class="desc">Description</h3>
973 * Dispatch unsolicited FCP_CMND frame that is assisted with auto xfer ready.
974 *
975 * @param node Node that originated the frame.
976 * @param seq Header/payload sequence buffers.
977 *
978 * @return Returns 0 if frame processed and RX buffers cleaned
979 * up appropriately, -1 if frame not handled and RX buffers need
980 * to be returned.
981 */
982static int32_t
983ocs_dispatch_fcp_cmd_auto_xfer_rdy(ocs_node_t *node, ocs_hw_sequence_t *seq)
984{
985	ocs_t *ocs = node->ocs;
986	fc_header_t	*fchdr = seq->header->dma.virt;
987	fcp_cmnd_iu_t	*cmnd = NULL;
988	ocs_io_t	*io = NULL;
989	uint64_t	lun = UINT64_MAX;
990	int32_t		rc = 0;
991
992	ocs_assert(seq->payload, -1);
993	cmnd = seq->payload->dma.virt;
994
995	/* perform FCP_CMND validation check(s) */
996	if (ocs_validate_fcp_cmd(ocs, seq)) {
997		return -1;
998	}
999
1000	/* make sure first burst or auto xfer_rdy is enabled */
1001	if (!seq->auto_xrdy) {
1002		node_printf(node, "IO is not Auto Xfr Rdy assisted, dropping FCP_CMND\n");
1003		return -1;
1004	}
1005
1006	lun = CAM_EXTLUN_BYTE_SWIZZLE(be64dec(cmnd->fcp_lun));
1007
1008	/* TODO should there be a check here for an error? Why do any of the
1009	 * below if the LUN decode failed? */
1010	io = ocs_scsi_io_alloc(node, OCS_SCSI_IO_ROLE_RESPONDER);
1011	if (io == NULL) {
1012		uint32_t send_frame_capable;
1013
1014		/* If we have SEND_FRAME capability, then use it to send task set full or busy */
1015		rc = ocs_hw_get(&ocs->hw, OCS_HW_SEND_FRAME_CAPABLE, &send_frame_capable);
1016		if ((rc == 0) && send_frame_capable) {
1017			rc = ocs_sframe_send_task_set_full_or_busy(node, seq);
1018			if (rc) {
1019				ocs_log_test(ocs, "ocs_sframe_send_task_set_full_or_busy failed: %d\n", rc);
1020			}
1021			return rc;
1022		}
1023
1024		ocs_log_err(ocs, "IO allocation failed ox_id %04x\n", ocs_be16toh(fchdr->ox_id));
1025		return -1;
1026	}
1027	io->hw_priv = seq->hw_priv;
1028
1029	/* RQ pair, if we got here, SIT=0 */
1030	ocs_populate_io_fcp_cmd(io, cmnd, fchdr, FALSE);
1031
1032	if (cmnd->task_management_flags) {
1033		/* first burst command better not be a TMF */
1034		ocs_log_err(ocs, "TMF flags set 0x%x\n", cmnd->task_management_flags);
1035		ocs_scsi_io_free(io);
1036		return -1;
1037	} else {
1038		uint32_t flags = ocs_get_flags_fcp_cmd(cmnd);
1039
1040		/* activate HW IO */
1041		ocs_hw_io_activate_port_owned(&ocs->hw, seq->hio);
1042		io->hio = seq->hio;
1043		seq->hio->ul_io = io;
1044		io->tgt_task_tag = seq->hio->indicator;
1045
1046		/* Note: Data buffers are received in another call */
1047		ocs_scsi_recv_cmd_first_burst(io, lun, cmnd->fcp_cdb,
1048					      sizeof(cmnd->fcp_cdb) +
1049					      (cmnd->additional_fcp_cdb_length * sizeof(uint32_t)),
1050					      flags, NULL, 0);
1051	}
1052
1053	/* FCP_CMND processed, return RX buffer to the chip */
1054	ocs_hw_sequence_free(&ocs->hw, seq);
1055	return 0;
1056}
1057
1058/**
1059 * @ingroup unsol
1060 * @brief Dispatch FCP data frames for auto xfer ready.
1061 *
1062 * <h3 class="desc">Description</h3>
1063 * Dispatch unsolicited FCP data frames (auto xfer ready)
1064 * containing sequence initiative transferred (SIT=1).
1065 *
1066 * @param node Node that originated the frame.
1067 * @param seq Header/payload sequence buffers.
1068 *
1069 * @return Returns 0 if frame processed and RX buffers cleaned
1070 * up appropriately, -1 if frame not handled.
1071 */
1072
1073static int32_t
1074ocs_dispatch_fcp_data(ocs_node_t *node, ocs_hw_sequence_t *seq)
1075{
1076	ocs_t *ocs = node->ocs;
1077	ocs_hw_t *hw = &ocs->hw;
1078	ocs_hw_io_t *hio = seq->hio;
1079	ocs_io_t	*io;
1080	ocs_dma_t fburst[1];
1081
1082	ocs_assert(seq->payload, -1);
1083	ocs_assert(hio, -1);
1084
1085	io = hio->ul_io;
1086	if (io == NULL) {
1087		ocs_log_err(ocs, "data received for NULL io, xri=0x%x\n",
1088			    hio->indicator);
1089		return -1;
1090	}
1091
1092	/*
1093	 * We only support data completions for auto xfer ready. Make sure
1094	 * this is a port owned XRI.
1095	 */
1096	if (!ocs_hw_is_io_port_owned(hw, seq->hio)) {
1097		ocs_log_err(ocs, "data received for host owned XRI, xri=0x%x\n",
1098			    hio->indicator);
1099		return -1;
1100	}
1101
1102	/* For error statuses, pass the error to the target back end */
1103	if (seq->status != OCS_HW_UNSOL_SUCCESS) {
1104		ocs_log_err(ocs, "data with status 0x%x received, xri=0x%x\n",
1105			    seq->status, hio->indicator);
1106
1107		/*
1108		 * In this case, there is an existing, in-use HW IO that
1109		 * first may need to be aborted. Then, the backend will be
1110		 * notified of the error while waiting for the data.
1111		 */
1112		ocs_port_owned_abort(ocs, seq->hio);
1113
1114		/*
1115		 * HW IO has already been allocated and is waiting for data.
1116		 * Need to tell backend that an error has occurred.
1117		 */
1118		ocs_scsi_recv_cmd_first_burst(io, 0, NULL, 0, OCS_SCSI_FIRST_BURST_ERR, NULL, 0);
1119		return -1;
1120	}
1121
1122	/* sequence initiative has been transferred */
1123	io->seq_init = 1;
1124
1125	/* convert the array of pointers to the correct type, to send to backend */
1126	fburst[0] = seq->payload->dma;
1127
1128	/* the amount of first burst data was saved as "acculated sequence length" */
1129	io->transferred = seq->payload->dma.len;
1130
1131	if (ocs_scsi_recv_cmd_first_burst(io, 0, NULL, 0, 0,
1132					  fburst, io->transferred)) {
1133		ocs_log_err(ocs, "error passing first burst, xri=0x%x, oxid=0x%x\n",
1134			    hio->indicator, io->init_task_tag);
1135	}
1136
1137	/* Free the header and all the accumulated payload buffers */
1138	ocs_hw_sequence_free(&ocs->hw, seq);
1139	return 0;
1140}
1141
1142
1143/**
1144 * @ingroup unsol
1145 * @brief Handle the callback for the TMF FUNCTION_REJECTED response.
1146 *
1147 * <h3 class="desc">Description</h3>
1148 * Handle the callback of a send TMF FUNCTION_REJECTED response request.
1149 *
1150 * @param io Pointer to the IO context.
1151 * @param scsi_status Status of the response.
1152 * @param flags Callback flags.
1153 * @param arg Callback argument.
1154 *
1155 * @return Returns 0 on success, or a negative error value on failure.
1156 */
1157
1158static int32_t
1159ocs_fc_tmf_rejected_cb(ocs_io_t *io, ocs_scsi_io_status_e scsi_status, uint32_t flags, void *arg)
1160{
1161	ocs_scsi_io_free(io);
1162	return 0;
1163}
1164
1165/**
1166 * @brief Return next FC frame on node->pend_frames list
1167 *
1168 * The next FC frame on the node->pend_frames list is returned, or NULL
1169 * if the list is empty.
1170 *
1171 * @param pend_list Pending list to be purged.
1172 * @param list_lock Lock that protects pending list.
1173 *
1174 * @return Returns pointer to the next FC frame, or NULL if the pending frame list
1175 * is empty.
1176 */
1177static ocs_hw_sequence_t *
1178ocs_frame_next(ocs_list_t *pend_list, ocs_lock_t *list_lock)
1179{
1180	ocs_hw_sequence_t *frame = NULL;
1181
1182	ocs_lock(list_lock);
1183		frame = ocs_list_remove_head(pend_list);
1184	ocs_unlock(list_lock);
1185	return frame;
1186}
1187
1188/**
1189 * @brief Process send fcp response frame callback
1190 *
1191 * The function is called when the send FCP response posting has completed. Regardless
1192 * of the outcome, the sequence is freed.
1193 *
1194 * @param arg Pointer to originator frame sequence.
1195 * @param cqe Pointer to completion queue entry.
1196 * @param status Status of operation.
1197 *
1198 * @return None.
1199 */
1200static void
1201ocs_sframe_common_send_cb(void *arg, uint8_t *cqe, int32_t status)
1202{
1203	ocs_hw_send_frame_context_t *ctx = arg;
1204	ocs_hw_t *hw = ctx->hw;
1205
1206	/* Free WQ completion callback */
1207	ocs_hw_reqtag_free(hw, ctx->wqcb);
1208
1209	/* Free sequence */
1210	ocs_hw_sequence_free(hw, ctx->seq);
1211}
1212
1213/**
1214 * @brief Send a frame, common code
1215 *
1216 * A frame is sent using SEND_FRAME, the R_CTL/F_CTL/TYPE may be specified, the payload is
1217 * sent as a single frame.
1218 *
1219 * Memory resources are allocated from RQ buffers contained in the passed in sequence data.
1220 *
1221 * @param node Pointer to node object.
1222 * @param seq Pointer to sequence object.
1223 * @param r_ctl R_CTL value to place in FC header.
1224 * @param info INFO value to place in FC header.
1225 * @param f_ctl F_CTL value to place in FC header.
1226 * @param type TYPE value to place in FC header.
1227 * @param payload Pointer to payload data
1228 * @param payload_len Length of payload in bytes.
1229 *
1230 * @return Returns 0 on success, or a negative error code value on failure.
1231 */
1232static int32_t
1233ocs_sframe_common_send(ocs_node_t *node, ocs_hw_sequence_t *seq, uint8_t r_ctl, uint8_t info, uint32_t f_ctl,
1234		       uint8_t type, void *payload, uint32_t payload_len)
1235{
1236	ocs_t *ocs = node->ocs;
1237	ocs_hw_t *hw = &ocs->hw;
1238	ocs_hw_rtn_e rc = 0;
1239	fc_header_t *behdr = seq->header->dma.virt;
1240	fc_header_le_t hdr;
1241	uint32_t s_id = fc_be24toh(behdr->s_id);
1242	uint32_t d_id = fc_be24toh(behdr->d_id);
1243	uint16_t ox_id = ocs_be16toh(behdr->ox_id);
1244	uint16_t rx_id = ocs_be16toh(behdr->rx_id);
1245	ocs_hw_send_frame_context_t *ctx;
1246
1247	uint32_t heap_size = seq->payload->dma.size;
1248	uintptr_t heap_phys_base = seq->payload->dma.phys;
1249	uint8_t *heap_virt_base = seq->payload->dma.virt;
1250	uint32_t heap_offset = 0;
1251
1252	/* Build the FC header reusing the RQ header DMA buffer */
1253	ocs_memset(&hdr, 0, sizeof(hdr));
1254	hdr.d_id = s_id;			/* send it back to whomever sent it to us */
1255	hdr.r_ctl = r_ctl;
1256	hdr.info = info;
1257	hdr.s_id = d_id;
1258	hdr.cs_ctl = 0;
1259	hdr.f_ctl = f_ctl;
1260	hdr.type = type;
1261	hdr.seq_cnt = 0;
1262	hdr.df_ctl = 0;
1263
1264	/*
1265	 * send_frame_seq_id is an atomic, we just let it increment, while storing only
1266	 * the low 8 bits to hdr->seq_id
1267	 */
1268	hdr.seq_id = (uint8_t) ocs_atomic_add_return(&hw->send_frame_seq_id, 1);
1269
1270	hdr.rx_id = rx_id;
1271	hdr.ox_id = ox_id;
1272	hdr.parameter = 0;
1273
1274	/* Allocate and fill in the send frame request context */
1275	ctx = (void*)(heap_virt_base + heap_offset);
1276	heap_offset += sizeof(*ctx);
1277	ocs_assert(heap_offset < heap_size, -1);
1278	ocs_memset(ctx, 0, sizeof(*ctx));
1279
1280	/* Save sequence */
1281	ctx->seq = seq;
1282
1283	/* Allocate a response payload DMA buffer from the heap */
1284	ctx->payload.phys = heap_phys_base + heap_offset;
1285	ctx->payload.virt = heap_virt_base + heap_offset;
1286	ctx->payload.size = payload_len;
1287	ctx->payload.len = payload_len;
1288	heap_offset += payload_len;
1289	ocs_assert(heap_offset <= heap_size, -1);
1290
1291	/* Copy the payload in */
1292	ocs_memcpy(ctx->payload.virt, payload, payload_len);
1293
1294	/* Send */
1295	rc = ocs_hw_send_frame(&ocs->hw, (void*)&hdr, FC_SOFI3, FC_EOFT, &ctx->payload, ctx,
1296				ocs_sframe_common_send_cb, ctx);
1297	if (rc) {
1298		ocs_log_test(ocs, "ocs_hw_send_frame failed: %d\n", rc);
1299	}
1300
1301	return rc ? -1 : 0;
1302}
1303
1304/**
1305 * @brief Send FCP response using SEND_FRAME
1306 *
1307 * The FCP response is send using the SEND_FRAME function.
1308 *
1309 * @param node Pointer to node object.
1310 * @param seq Pointer to inbound sequence.
1311 * @param rsp Pointer to response data.
1312 * @param rsp_len Length of response data, in bytes.
1313 *
1314 * @return Returns 0 on success, or a negative error code value on failure.
1315 */
1316static int32_t
1317ocs_sframe_send_fcp_rsp(ocs_node_t *node, ocs_hw_sequence_t *seq, void *rsp, uint32_t rsp_len)
1318{
1319	return ocs_sframe_common_send(node, seq,
1320				      FC_RCTL_FC4_DATA,
1321				      FC_RCTL_INFO_CMD_STATUS,
1322				      FC_FCTL_EXCHANGE_RESPONDER |
1323					      FC_FCTL_LAST_SEQUENCE |
1324					      FC_FCTL_END_SEQUENCE |
1325					      FC_FCTL_SEQUENCE_INITIATIVE,
1326				      FC_TYPE_FCP,
1327				      rsp, rsp_len);
1328}
1329
1330/**
1331 * @brief Send task set full response
1332 *
1333 * Return a task set full or busy response using send frame.
1334 *
1335 * @param node Pointer to node object.
1336 * @param seq Pointer to originator frame sequence.
1337 *
1338 * @return Returns 0 on success, or a negative error code value on failure.
1339 */
1340static int32_t
1341ocs_sframe_send_task_set_full_or_busy(ocs_node_t *node, ocs_hw_sequence_t *seq)
1342{
1343	fcp_rsp_iu_t fcprsp;
1344	fcp_cmnd_iu_t *fcpcmd = seq->payload->dma.virt;
1345	uint32_t *fcp_dl_ptr;
1346	uint32_t fcp_dl;
1347	int32_t rc = 0;
1348
1349	/* extract FCP_DL from FCP command*/
1350	fcp_dl_ptr = (uint32_t*)(&(fcpcmd->fcp_cdb_and_dl));
1351	fcp_dl_ptr += fcpcmd->additional_fcp_cdb_length;
1352	fcp_dl = ocs_be32toh(*fcp_dl_ptr);
1353
1354	/* construct task set full or busy response */
1355	ocs_memset(&fcprsp, 0, sizeof(fcprsp));
1356	ocs_lock(&node->active_ios_lock);
1357		fcprsp.scsi_status = ocs_list_empty(&node->active_ios) ? SCSI_STATUS_BUSY : SCSI_STATUS_TASK_SET_FULL;
1358	ocs_unlock(&node->active_ios_lock);
1359	*((uint32_t*)&fcprsp.fcp_resid) = fcp_dl;
1360
1361	/* send it using send_frame */
1362	rc = ocs_sframe_send_fcp_rsp(node, seq, &fcprsp, sizeof(fcprsp) - sizeof(fcprsp.data));
1363	if (rc) {
1364		ocs_log_test(node->ocs, "ocs_sframe_send_fcp_rsp failed: %d\n", rc);
1365	}
1366	return rc;
1367}
1368
1369/**
1370 * @brief Send BA_ACC using sent frame
1371 *
1372 * A BA_ACC is sent using SEND_FRAME
1373 *
1374 * @param node Pointer to node object.
1375 * @param seq Pointer to originator frame sequence.
1376 *
1377 * @return Returns 0 on success, or a negative error code value on failure.
1378 */
1379int32_t
1380ocs_sframe_send_bls_acc(ocs_node_t *node,  ocs_hw_sequence_t *seq)
1381{
1382	fc_header_t *behdr = seq->header->dma.virt;
1383	uint16_t ox_id = ocs_be16toh(behdr->ox_id);
1384	uint16_t rx_id = ocs_be16toh(behdr->rx_id);
1385	fc_ba_acc_payload_t acc = {0};
1386
1387	acc.ox_id = ocs_htobe16(ox_id);
1388	acc.rx_id = ocs_htobe16(rx_id);
1389	acc.low_seq_cnt = UINT16_MAX;
1390	acc.high_seq_cnt = UINT16_MAX;
1391
1392	return ocs_sframe_common_send(node, seq,
1393				      FC_RCTL_BLS,
1394				      FC_RCTL_INFO_UNSOL_DATA,
1395				      FC_FCTL_EXCHANGE_RESPONDER |
1396					      FC_FCTL_LAST_SEQUENCE |
1397					      FC_FCTL_END_SEQUENCE,
1398				      FC_TYPE_BASIC_LINK,
1399				      &acc, sizeof(acc));
1400}
1401