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