xref: /freebsd/sys/dev/ocs_fc/ocs_unsol.c (revision 13ea0450a9c8742119d36f3bf8f47accdce46e54)
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 
57 static int32_t ocs_unsol_process(ocs_t *ocs, ocs_hw_sequence_t *seq);
58 static int32_t ocs_dispatch_fcp_cmd(ocs_node_t *node, ocs_hw_sequence_t *seq);
59 static int32_t ocs_dispatch_fcp_cmd_auto_xfer_rdy(ocs_node_t *node, ocs_hw_sequence_t *seq);
60 static int32_t ocs_dispatch_fcp_data(ocs_node_t *node, ocs_hw_sequence_t *seq);
61 static int32_t ocs_domain_dispatch_frame(void *arg, ocs_hw_sequence_t *seq);
62 static int32_t ocs_node_dispatch_frame(void *arg, ocs_hw_sequence_t *seq);
63 static int32_t ocs_fc_tmf_rejected_cb(ocs_io_t *io, ocs_scsi_io_status_e scsi_status, uint32_t flags, void *arg);
64 static ocs_hw_sequence_t *ocs_frame_next(ocs_list_t *pend_list, ocs_lock_t *list_lock);
65 static uint8_t ocs_node_frames_held(void *arg);
66 static uint8_t ocs_domain_frames_held(void *arg);
67 static int32_t ocs_purge_pending(ocs_t *ocs, ocs_list_t *pend_list, ocs_lock_t *list_lock);
68 static 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  */
79 int32_t
80 ocs_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  */
117 static int32_t
118 ocs_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  */
134 static void
135 ocs_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 
162 int32_t
163 ocs_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  */
201 static int32_t
202 ocs_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 
276 int32_t
277 ocs_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 
334 int32_t
335 ocs_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 
395 static int32_t
396 ocs_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 
429 int32_t
430 ocs_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 
448 int32_t
449 ocs_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 
472 static uint8_t
473 ocs_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 
490 static uint8_t
491 ocs_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 
516 void
517 ocs_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 
544 void
545 ocs_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 
576 static __inline int32_t
577 ocs_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  */
670 static int32_t
671 ocs_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 
760 static void
761 ocs_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 
792 static int32_t
793 ocs_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 
815 static void
816 ocs_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 
839 static uint32_t
840 ocs_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 	if (cmnd->wrdata)
861 		flags |= OCS_SCSI_CMD_DIR_IN;
862 	if (cmnd->rddata)
863 		flags |= OCS_SCSI_CMD_DIR_OUT;
864 
865 	return flags;
866 }
867 
868 /**
869  * @ingroup unsol
870  * @brief Dispatch unsolicited FCP_CMND frame.
871  *
872  * <h3 class="desc">Description</h3>
873  * Dispatch unsolicited FCP_CMND frame. RQ Pair mode - always
874  * used for RQ Pair mode since first burst is not supported.
875  *
876  * @param node Node that originated the frame.
877  * @param seq Header/payload sequence buffers.
878  *
879  * @return Returns 0 if frame processed and RX buffers cleaned
880  * up appropriately, -1 if frame not handled and RX buffers need
881  * to be returned.
882  */
883 static int32_t
884 ocs_dispatch_fcp_cmd(ocs_node_t *node, ocs_hw_sequence_t *seq)
885 {
886 	ocs_t *ocs = node->ocs;
887 	fc_header_t	*fchdr = seq->header->dma.virt;
888 	fcp_cmnd_iu_t	*cmnd = NULL;
889 	ocs_io_t	*io = NULL;
890 	fc_vm_header_t 	*vhdr;
891 	uint8_t 	df_ctl;
892 	uint64_t	lun = UINT64_MAX;
893 	int32_t		rc = 0;
894 
895 	ocs_assert(seq->payload, -1);
896 	cmnd = seq->payload->dma.virt;
897 
898 	/* perform FCP_CMND validation check(s) */
899 	if (ocs_validate_fcp_cmd(ocs, seq)) {
900 		return -1;
901 	}
902 
903 	lun = CAM_EXTLUN_BYTE_SWIZZLE(be64dec(cmnd->fcp_lun));
904 	if (lun == UINT64_MAX) {
905 		return -1;
906 	}
907 
908 	io = ocs_scsi_io_alloc(node, OCS_SCSI_IO_ROLE_RESPONDER);
909 	if (io == NULL) {
910 		uint32_t send_frame_capable;
911 
912 		/* If we have SEND_FRAME capability, then use it to send task set full or busy */
913 		rc = ocs_hw_get(&ocs->hw, OCS_HW_SEND_FRAME_CAPABLE, &send_frame_capable);
914 		if ((rc == 0) && send_frame_capable) {
915 			rc = ocs_sframe_send_task_set_full_or_busy(node, seq);
916 			if (rc) {
917 				ocs_log_test(ocs, "ocs_sframe_send_task_set_full_or_busy failed: %d\n", rc);
918 			}
919 			return rc;
920 		}
921 
922 		ocs_log_err(ocs, "IO allocation failed ox_id %04x\n", ocs_be16toh(fchdr->ox_id));
923 		return -1;
924 	}
925 	io->hw_priv = seq->hw_priv;
926 
927 	/* Check if the CMD has vmheader. */
928 	io->app_id = 0;
929 	df_ctl = fchdr->df_ctl;
930 	if (df_ctl & FC_DFCTL_DEVICE_HDR_16_MASK) {
931 		uint32_t vmhdr_offset = 0;
932 		/* Presence of VMID. Get the vm header offset. */
933 		if (df_ctl & FC_DFCTL_ESP_HDR_MASK) {
934 			vmhdr_offset += FC_DFCTL_ESP_HDR_SIZE;
935 			ocs_log_err(ocs, "ESP Header present. Fix ESP Size.\n");
936 		}
937 
938 		if (df_ctl & FC_DFCTL_NETWORK_HDR_MASK) {
939 			vmhdr_offset += FC_DFCTL_NETWORK_HDR_SIZE;
940 		}
941 		vhdr = (fc_vm_header_t *) ((char *)fchdr + sizeof(fc_header_t) + vmhdr_offset);
942 		io->app_id = ocs_be32toh(vhdr->src_vmid);
943 	}
944 
945 	/* RQ pair, if we got here, SIT=1 */
946 	ocs_populate_io_fcp_cmd(io, cmnd, fchdr, TRUE);
947 
948 	if (cmnd->task_management_flags) {
949 		ocs_dispatch_unsolicited_tmf(io, cmnd->task_management_flags, node, lun);
950 	} else {
951 		uint32_t flags = ocs_get_flags_fcp_cmd(cmnd);
952 
953 		/* can return failure for things like task set full and UAs,
954 		 * no need to treat as a dropped frame if rc != 0
955 		 */
956 		ocs_scsi_recv_cmd(io, lun, cmnd->fcp_cdb,
957 				  sizeof(cmnd->fcp_cdb) +
958 				  (cmnd->additional_fcp_cdb_length * sizeof(uint32_t)),
959 				  flags);
960 	}
961 
962 	/* successfully processed, now return RX buffer to the chip */
963 	ocs_hw_sequence_free(&ocs->hw, seq);
964 	return 0;
965 }
966 
967 /**
968  * @ingroup unsol
969  * @brief Dispatch unsolicited FCP_CMND frame (auto xfer rdy).
970  *
971  * <h3 class="desc">Description</h3>
972  * Dispatch unsolicited FCP_CMND frame that is assisted with auto xfer ready.
973  *
974  * @param node Node that originated the frame.
975  * @param seq Header/payload sequence buffers.
976  *
977  * @return Returns 0 if frame processed and RX buffers cleaned
978  * up appropriately, -1 if frame not handled and RX buffers need
979  * to be returned.
980  */
981 static int32_t
982 ocs_dispatch_fcp_cmd_auto_xfer_rdy(ocs_node_t *node, ocs_hw_sequence_t *seq)
983 {
984 	ocs_t *ocs = node->ocs;
985 	fc_header_t	*fchdr = seq->header->dma.virt;
986 	fcp_cmnd_iu_t	*cmnd = NULL;
987 	ocs_io_t	*io = NULL;
988 	uint64_t	lun = UINT64_MAX;
989 	int32_t		rc = 0;
990 
991 	ocs_assert(seq->payload, -1);
992 	cmnd = seq->payload->dma.virt;
993 
994 	/* perform FCP_CMND validation check(s) */
995 	if (ocs_validate_fcp_cmd(ocs, seq)) {
996 		return -1;
997 	}
998 
999 	/* make sure first burst or auto xfer_rdy is enabled */
1000 	if (!seq->auto_xrdy) {
1001 		node_printf(node, "IO is not Auto Xfr Rdy assisted, dropping FCP_CMND\n");
1002 		return -1;
1003 	}
1004 
1005 	lun = CAM_EXTLUN_BYTE_SWIZZLE(be64dec(cmnd->fcp_lun));
1006 
1007 	/* TODO should there be a check here for an error? Why do any of the
1008 	 * below if the LUN decode failed? */
1009 	io = ocs_scsi_io_alloc(node, OCS_SCSI_IO_ROLE_RESPONDER);
1010 	if (io == NULL) {
1011 		uint32_t send_frame_capable;
1012 
1013 		/* If we have SEND_FRAME capability, then use it to send task set full or busy */
1014 		rc = ocs_hw_get(&ocs->hw, OCS_HW_SEND_FRAME_CAPABLE, &send_frame_capable);
1015 		if ((rc == 0) && send_frame_capable) {
1016 			rc = ocs_sframe_send_task_set_full_or_busy(node, seq);
1017 			if (rc) {
1018 				ocs_log_test(ocs, "ocs_sframe_send_task_set_full_or_busy failed: %d\n", rc);
1019 			}
1020 			return rc;
1021 		}
1022 
1023 		ocs_log_err(ocs, "IO allocation failed ox_id %04x\n", ocs_be16toh(fchdr->ox_id));
1024 		return -1;
1025 	}
1026 	io->hw_priv = seq->hw_priv;
1027 
1028 	/* RQ pair, if we got here, SIT=0 */
1029 	ocs_populate_io_fcp_cmd(io, cmnd, fchdr, FALSE);
1030 
1031 	if (cmnd->task_management_flags) {
1032 		/* first burst command better not be a TMF */
1033 		ocs_log_err(ocs, "TMF flags set 0x%x\n", cmnd->task_management_flags);
1034 		ocs_scsi_io_free(io);
1035 		return -1;
1036 	} else {
1037 		uint32_t flags = ocs_get_flags_fcp_cmd(cmnd);
1038 
1039 		/* activate HW IO */
1040 		ocs_hw_io_activate_port_owned(&ocs->hw, seq->hio);
1041 		io->hio = seq->hio;
1042 		seq->hio->ul_io = io;
1043 		io->tgt_task_tag = seq->hio->indicator;
1044 
1045 		/* Note: Data buffers are received in another call */
1046 		ocs_scsi_recv_cmd_first_burst(io, lun, cmnd->fcp_cdb,
1047 					      sizeof(cmnd->fcp_cdb) +
1048 					      (cmnd->additional_fcp_cdb_length * sizeof(uint32_t)),
1049 					      flags, NULL, 0);
1050 	}
1051 
1052 	/* FCP_CMND processed, return RX buffer to the chip */
1053 	ocs_hw_sequence_free(&ocs->hw, seq);
1054 	return 0;
1055 }
1056 
1057 /**
1058  * @ingroup unsol
1059  * @brief Dispatch FCP data frames for auto xfer ready.
1060  *
1061  * <h3 class="desc">Description</h3>
1062  * Dispatch unsolicited FCP data frames (auto xfer ready)
1063  * containing sequence initiative transferred (SIT=1).
1064  *
1065  * @param node Node that originated the frame.
1066  * @param seq Header/payload sequence buffers.
1067  *
1068  * @return Returns 0 if frame processed and RX buffers cleaned
1069  * up appropriately, -1 if frame not handled.
1070  */
1071 
1072 static int32_t
1073 ocs_dispatch_fcp_data(ocs_node_t *node, ocs_hw_sequence_t *seq)
1074 {
1075 	ocs_t *ocs = node->ocs;
1076 	ocs_hw_t *hw = &ocs->hw;
1077 	ocs_hw_io_t *hio = seq->hio;
1078 	ocs_io_t	*io;
1079 	ocs_dma_t fburst[1];
1080 
1081 	ocs_assert(seq->payload, -1);
1082 	ocs_assert(hio, -1);
1083 
1084 	io = hio->ul_io;
1085 	if (io == NULL) {
1086 		ocs_log_err(ocs, "data received for NULL io, xri=0x%x\n",
1087 			    hio->indicator);
1088 		return -1;
1089 	}
1090 
1091 	/*
1092 	 * We only support data completions for auto xfer ready. Make sure
1093 	 * this is a port owned XRI.
1094 	 */
1095 	if (!ocs_hw_is_io_port_owned(hw, seq->hio)) {
1096 		ocs_log_err(ocs, "data received for host owned XRI, xri=0x%x\n",
1097 			    hio->indicator);
1098 		return -1;
1099 	}
1100 
1101 	/* For error statuses, pass the error to the target back end */
1102 	if (seq->status != OCS_HW_UNSOL_SUCCESS) {
1103 		ocs_log_err(ocs, "data with status 0x%x received, xri=0x%x\n",
1104 			    seq->status, hio->indicator);
1105 
1106 		/*
1107 		 * In this case, there is an existing, in-use HW IO that
1108 		 * first may need to be aborted. Then, the backend will be
1109 		 * notified of the error while waiting for the data.
1110 		 */
1111 		ocs_port_owned_abort(ocs, seq->hio);
1112 
1113 		/*
1114 		 * HW IO has already been allocated and is waiting for data.
1115 		 * Need to tell backend that an error has occurred.
1116 		 */
1117 		ocs_scsi_recv_cmd_first_burst(io, 0, NULL, 0, OCS_SCSI_FIRST_BURST_ERR, NULL, 0);
1118 		return -1;
1119 	}
1120 
1121 	/* sequence initiative has been transferred */
1122 	io->seq_init = 1;
1123 
1124 	/* convert the array of pointers to the correct type, to send to backend */
1125 	fburst[0] = seq->payload->dma;
1126 
1127 	/* the amount of first burst data was saved as "acculated sequence length" */
1128 	io->transferred = seq->payload->dma.len;
1129 
1130 	if (ocs_scsi_recv_cmd_first_burst(io, 0, NULL, 0, 0,
1131 					  fburst, io->transferred)) {
1132 		ocs_log_err(ocs, "error passing first burst, xri=0x%x, oxid=0x%x\n",
1133 			    hio->indicator, io->init_task_tag);
1134 	}
1135 
1136 	/* Free the header and all the accumulated payload buffers */
1137 	ocs_hw_sequence_free(&ocs->hw, seq);
1138 	return 0;
1139 }
1140 
1141 
1142 /**
1143  * @ingroup unsol
1144  * @brief Handle the callback for the TMF FUNCTION_REJECTED response.
1145  *
1146  * <h3 class="desc">Description</h3>
1147  * Handle the callback of a send TMF FUNCTION_REJECTED response request.
1148  *
1149  * @param io Pointer to the IO context.
1150  * @param scsi_status Status of the response.
1151  * @param flags Callback flags.
1152  * @param arg Callback argument.
1153  *
1154  * @return Returns 0 on success, or a negative error value on failure.
1155  */
1156 
1157 static int32_t
1158 ocs_fc_tmf_rejected_cb(ocs_io_t *io, ocs_scsi_io_status_e scsi_status, uint32_t flags, void *arg)
1159 {
1160 	ocs_scsi_io_free(io);
1161 	return 0;
1162 }
1163 
1164 /**
1165  * @brief Return next FC frame on node->pend_frames list
1166  *
1167  * The next FC frame on the node->pend_frames list is returned, or NULL
1168  * if the list is empty.
1169  *
1170  * @param pend_list Pending list to be purged.
1171  * @param list_lock Lock that protects pending list.
1172  *
1173  * @return Returns pointer to the next FC frame, or NULL if the pending frame list
1174  * is empty.
1175  */
1176 static ocs_hw_sequence_t *
1177 ocs_frame_next(ocs_list_t *pend_list, ocs_lock_t *list_lock)
1178 {
1179 	ocs_hw_sequence_t *frame = NULL;
1180 
1181 	ocs_lock(list_lock);
1182 		frame = ocs_list_remove_head(pend_list);
1183 	ocs_unlock(list_lock);
1184 	return frame;
1185 }
1186 
1187 /**
1188  * @brief Process send fcp response frame callback
1189  *
1190  * The function is called when the send FCP response posting has completed. Regardless
1191  * of the outcome, the sequence is freed.
1192  *
1193  * @param arg Pointer to originator frame sequence.
1194  * @param cqe Pointer to completion queue entry.
1195  * @param status Status of operation.
1196  *
1197  * @return None.
1198  */
1199 static void
1200 ocs_sframe_common_send_cb(void *arg, uint8_t *cqe, int32_t status)
1201 {
1202 	ocs_hw_send_frame_context_t *ctx = arg;
1203 	ocs_hw_t *hw = ctx->hw;
1204 
1205 	/* Free WQ completion callback */
1206 	ocs_hw_reqtag_free(hw, ctx->wqcb);
1207 
1208 	/* Free sequence */
1209 	ocs_hw_sequence_free(hw, ctx->seq);
1210 }
1211 
1212 /**
1213  * @brief Send a frame, common code
1214  *
1215  * A frame is sent using SEND_FRAME, the R_CTL/F_CTL/TYPE may be specified, the payload is
1216  * sent as a single frame.
1217  *
1218  * Memory resources are allocated from RQ buffers contained in the passed in sequence data.
1219  *
1220  * @param node Pointer to node object.
1221  * @param seq Pointer to sequence object.
1222  * @param r_ctl R_CTL value to place in FC header.
1223  * @param info INFO value to place in FC header.
1224  * @param f_ctl F_CTL value to place in FC header.
1225  * @param type TYPE value to place in FC header.
1226  * @param payload Pointer to payload data
1227  * @param payload_len Length of payload in bytes.
1228  *
1229  * @return Returns 0 on success, or a negative error code value on failure.
1230  */
1231 static int32_t
1232 ocs_sframe_common_send(ocs_node_t *node, ocs_hw_sequence_t *seq, uint8_t r_ctl, uint8_t info, uint32_t f_ctl,
1233 		       uint8_t type, void *payload, uint32_t payload_len)
1234 {
1235 	ocs_t *ocs = node->ocs;
1236 	ocs_hw_t *hw = &ocs->hw;
1237 	ocs_hw_rtn_e rc = 0;
1238 	fc_header_t *behdr = seq->header->dma.virt;
1239 	fc_header_le_t hdr;
1240 	uint32_t s_id = fc_be24toh(behdr->s_id);
1241 	uint32_t d_id = fc_be24toh(behdr->d_id);
1242 	uint16_t ox_id = ocs_be16toh(behdr->ox_id);
1243 	uint16_t rx_id = ocs_be16toh(behdr->rx_id);
1244 	ocs_hw_send_frame_context_t *ctx;
1245 
1246 	uint32_t heap_size = seq->payload->dma.size;
1247 	uintptr_t heap_phys_base = seq->payload->dma.phys;
1248 	uint8_t *heap_virt_base = seq->payload->dma.virt;
1249 	uint32_t heap_offset = 0;
1250 
1251 	/* Build the FC header reusing the RQ header DMA buffer */
1252 	ocs_memset(&hdr, 0, sizeof(hdr));
1253 	hdr.d_id = s_id;			/* send it back to whomever sent it to us */
1254 	hdr.r_ctl = r_ctl;
1255 	hdr.info = info;
1256 	hdr.s_id = d_id;
1257 	hdr.cs_ctl = 0;
1258 	hdr.f_ctl = f_ctl;
1259 	hdr.type = type;
1260 	hdr.seq_cnt = 0;
1261 	hdr.df_ctl = 0;
1262 
1263 	/*
1264 	 * send_frame_seq_id is an atomic, we just let it increment, while storing only
1265 	 * the low 8 bits to hdr->seq_id
1266 	 */
1267 	hdr.seq_id = (uint8_t) ocs_atomic_add_return(&hw->send_frame_seq_id, 1);
1268 
1269 	hdr.rx_id = rx_id;
1270 	hdr.ox_id = ox_id;
1271 	hdr.parameter = 0;
1272 
1273 	/* Allocate and fill in the send frame request context */
1274 	ctx = (void*)(heap_virt_base + heap_offset);
1275 	heap_offset += sizeof(*ctx);
1276 	ocs_assert(heap_offset < heap_size, -1);
1277 	ocs_memset(ctx, 0, sizeof(*ctx));
1278 
1279 	/* Save sequence */
1280 	ctx->seq = seq;
1281 
1282 	/* Allocate a response payload DMA buffer from the heap */
1283 	ctx->payload.phys = heap_phys_base + heap_offset;
1284 	ctx->payload.virt = heap_virt_base + heap_offset;
1285 	ctx->payload.size = payload_len;
1286 	ctx->payload.len = payload_len;
1287 	heap_offset += payload_len;
1288 	ocs_assert(heap_offset <= heap_size, -1);
1289 
1290 	/* Copy the payload in */
1291 	ocs_memcpy(ctx->payload.virt, payload, payload_len);
1292 
1293 	/* Send */
1294 	rc = ocs_hw_send_frame(&ocs->hw, (void*)&hdr, FC_SOFI3, FC_EOFT, &ctx->payload, ctx,
1295 				ocs_sframe_common_send_cb, ctx);
1296 	if (rc) {
1297 		ocs_log_test(ocs, "ocs_hw_send_frame failed: %d\n", rc);
1298 	}
1299 
1300 	return rc ? -1 : 0;
1301 }
1302 
1303 /**
1304  * @brief Send FCP response using SEND_FRAME
1305  *
1306  * The FCP response is send using the SEND_FRAME function.
1307  *
1308  * @param node Pointer to node object.
1309  * @param seq Pointer to inbound sequence.
1310  * @param rsp Pointer to response data.
1311  * @param rsp_len Length of response data, in bytes.
1312  *
1313  * @return Returns 0 on success, or a negative error code value on failure.
1314  */
1315 static int32_t
1316 ocs_sframe_send_fcp_rsp(ocs_node_t *node, ocs_hw_sequence_t *seq, void *rsp, uint32_t rsp_len)
1317 {
1318 	return ocs_sframe_common_send(node, seq,
1319 				      FC_RCTL_FC4_DATA,
1320 				      FC_RCTL_INFO_CMD_STATUS,
1321 				      FC_FCTL_EXCHANGE_RESPONDER |
1322 					      FC_FCTL_LAST_SEQUENCE |
1323 					      FC_FCTL_END_SEQUENCE |
1324 					      FC_FCTL_SEQUENCE_INITIATIVE,
1325 				      FC_TYPE_FCP,
1326 				      rsp, rsp_len);
1327 }
1328 
1329 /**
1330  * @brief Send task set full response
1331  *
1332  * Return a task set full or busy response using send frame.
1333  *
1334  * @param node Pointer to node object.
1335  * @param seq Pointer to originator frame sequence.
1336  *
1337  * @return Returns 0 on success, or a negative error code value on failure.
1338  */
1339 static int32_t
1340 ocs_sframe_send_task_set_full_or_busy(ocs_node_t *node, ocs_hw_sequence_t *seq)
1341 {
1342 	fcp_rsp_iu_t fcprsp;
1343 	fcp_cmnd_iu_t *fcpcmd = seq->payload->dma.virt;
1344 	uint32_t *fcp_dl_ptr;
1345 	uint32_t fcp_dl;
1346 	int32_t rc = 0;
1347 
1348 	/* extract FCP_DL from FCP command*/
1349 	fcp_dl_ptr = (uint32_t*)(&(fcpcmd->fcp_cdb_and_dl));
1350 	fcp_dl_ptr += fcpcmd->additional_fcp_cdb_length;
1351 	fcp_dl = ocs_be32toh(*fcp_dl_ptr);
1352 
1353 	/* construct task set full or busy response */
1354 	ocs_memset(&fcprsp, 0, sizeof(fcprsp));
1355 	ocs_lock(&node->active_ios_lock);
1356 		fcprsp.scsi_status = ocs_list_empty(&node->active_ios) ? SCSI_STATUS_BUSY : SCSI_STATUS_TASK_SET_FULL;
1357 	ocs_unlock(&node->active_ios_lock);
1358 	*((uint32_t*)&fcprsp.fcp_resid) = fcp_dl;
1359 
1360 	/* send it using send_frame */
1361 	rc = ocs_sframe_send_fcp_rsp(node, seq, &fcprsp, sizeof(fcprsp) - sizeof(fcprsp.data));
1362 	if (rc) {
1363 		ocs_log_test(node->ocs, "ocs_sframe_send_fcp_rsp failed: %d\n", rc);
1364 	}
1365 	return rc;
1366 }
1367 
1368 /**
1369  * @brief Send BA_ACC using sent frame
1370  *
1371  * A BA_ACC is sent using SEND_FRAME
1372  *
1373  * @param node Pointer to node object.
1374  * @param seq Pointer to originator frame sequence.
1375  *
1376  * @return Returns 0 on success, or a negative error code value on failure.
1377  */
1378 int32_t
1379 ocs_sframe_send_bls_acc(ocs_node_t *node,  ocs_hw_sequence_t *seq)
1380 {
1381 	fc_header_t *behdr = seq->header->dma.virt;
1382 	uint16_t ox_id = ocs_be16toh(behdr->ox_id);
1383 	uint16_t rx_id = ocs_be16toh(behdr->rx_id);
1384 	fc_ba_acc_payload_t acc = {0};
1385 
1386 	acc.ox_id = ocs_htobe16(ox_id);
1387 	acc.rx_id = ocs_htobe16(rx_id);
1388 	acc.low_seq_cnt = UINT16_MAX;
1389 	acc.high_seq_cnt = UINT16_MAX;
1390 
1391 	return ocs_sframe_common_send(node, seq,
1392 				      FC_RCTL_BLS,
1393 				      FC_RCTL_INFO_UNSOL_DATA,
1394 				      FC_FCTL_EXCHANGE_RESPONDER |
1395 					      FC_FCTL_LAST_SEQUENCE |
1396 					      FC_FCTL_END_SEQUENCE,
1397 				      FC_TYPE_BASIC_LINK,
1398 				      &acc, sizeof(acc));
1399 }
1400