Emulex Logo
OneCoreā„¢ Storage SDK Release 11.2
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
ocs_hal_rqpair.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2011-2015, Emulex
3  * All rights reserved.
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 /**
34  * @file
35  * This file contains code related to operating in RQ Pair mode.
36  *
37  */
38 
39 #include "ocs_os.h"
40 #include "ocs_hal.h"
41 
42 /* Uncomment this to turn on RQ debug */
43 // #define ENABLE_DEBUG_RQBUF
44 
45 static int32_t ocs_hal_rqpair_find(ocs_hal_t *hal, uint16_t rq_id);
46 static ocs_hal_sequence_t * ocs_hal_rqpair_get(ocs_hal_t *hal, uint16_t rqindex, uint16_t bufindex);
47 static int32_t ocs_hal_rqpair_put(ocs_hal_t *hal, ocs_hal_sequence_t *seq);
49 
50 /**
51  * @brief Process receive queue completions for RQ Pair mode.
52  *
53  * @par Description
54  * RQ completions are processed. In RQ pair mode, a single header and single payload
55  * buffer are received, and passed to the function that has registered for unsolicited
56  * callbacks.
57  *
58  * @param hal Hardware context.
59  * @param cq Pointer to HAL completion queue.
60  * @param cqe Completion queue entry.
61  *
62  * @return Returns 0 for success, or a negative error code value for failure.
63  */
64 
65 int32_t
66 ocs_hal_rqpair_process_rq(ocs_hal_t *hal, hal_cq_t *cq, uint8_t *cqe)
67 {
68  uint16_t rq_id;
69  uint32_t index;
70  int32_t rqindex;
71  int32_t rq_status;
72  uint32_t h_len;
73  uint32_t p_len;
74  ocs_hal_sequence_t *seq;
75  uint8_t code = cqe[SLI4_CQE_CODE_OFFSET];
76 
77  /* TODO: Merge this function with TOW handler */
78  rq_status = sli_fc_rqe_rqid_and_index(&hal->sli, cqe, &rq_id, &index);
79 
80  /* If possible, get the rqindex before checking for rq_status */
81  rqindex = ocs_hal_rqpair_find(hal, rq_id);
82  if (rqindex < 0) {
83  ocs_log_err(hal->os, "rq_status=%#x: rq_id lookup failed for id=%#x\n", rq_status, rq_id);
84  return -1;
85  }
86 
87  if (rq_status) {
88  ocs_log_err(hal->os, "RCQE status=%#x\n", rq_status);
89 
90  switch (rq_status) {
93  /* Get the RQ buffer */
94  seq = ocs_hal_rqpair_get(hal, rqindex, index);
95 
96  /* Return RQ buffer to the chip */
97  if (ocs_hal_rqpair_sequence_free(hal, seq))
98  ocs_log_err(hal->os, "failed to return buffers to RQ\n");
99 
100  break;
102  /* Since RQ buffers were not consumed, cannot return them to the chip */
103  hal_rq_t *rq = hal->hal_rq[hal->hal_rq_lookup[rqindex]];
104 
105  rq->rq_empty_warn_count++;
106  break;
107  }
109  /* Since RQ buffers were not consumed, cannot return them to the chip */
110  hal_rq_t *rq = hal->hal_rq[hal->hal_rq_lookup[rqindex]];
111 
112  rq->rq_empty_err_count++;
113  break;
114  }
115  default:
116  break;
117  }
118 
119  return -1;
120  }
121 
122  OCS_STAT({ hal_rq_t *rq = hal->hal_rq[hal->hal_rq_lookup[rqindex]]; rq->use_count++; rq->hdr_use_count++;
123  rq->payload_use_count++;})
124 
125  seq = ocs_hal_rqpair_get(hal, rqindex, index);
126  ocs_hal_assert(seq != NULL);
127 
128  if (code == SLI4_CQE_CODE_MARKER) {
129  /* This can come because of NVME marker, Just return the buffer to chip. */
130  if (ocs_hal_rqpair_sequence_free(hal, seq)) {
131  ocs_log_err(hal->os, "status=%#x, failed to return marker buffers to RQ\n",
132  rq_status);
133  }
134 
135  return 0;
136  }
137 
138  seq->hal = hal;
139  seq->tow = 0;
140  seq->tow_oox = 0;
141  seq->xri = 0;
142  seq->hio = NULL;
143 
144  sli_fc_rqe_length(&hal->sli, cqe, &h_len, &p_len);
145  seq->header->dma.len = h_len;
146  seq->payload->dma.len = p_len;
147  seq->fcfi = sli_fc_rqe_fcfi(&hal->sli, cqe);
148  seq->hal_priv = cq->eq;
149 
150  /* bounce enabled, single RQ, we snoop the ox_id to choose the cpuidx */
151  if (hal->config.bounce) {
152  fc_header_t *hdr = seq->header->dma.virt;
153  uint32_t s_id = fc_be24toh(hdr->s_id);
154  uint32_t d_id = fc_be24toh(hdr->d_id);
155  uint32_t ox_id = ocs_be16toh(hdr->ox_id);
156  if (hal->callback.bounce != NULL) {
157  (*hal->callback.bounce)(ocs_hal_unsol_process_bounce, seq, s_id, d_id, ox_id);
158  }
159  } else {
160  hal->callback.unsolicited(hal->args.unsolicited, seq);
161  }
162 
163  return 0;
164 }
165 
166 /**
167  * @brief Process receive queue completions for RQ Pair mode - Auto xfer rdy
168  *
169  * @par Description
170  * RQ completions are processed. In RQ pair mode, a single header and single payload
171  * buffer are received, and passed to the function that has registered for unsolicited
172  * callbacks.
173  *
174  * @param hal Hardware context.
175  * @param cq Pointer to HAL completion queue.
176  * @param cqe Completion queue entry.
177  *
178  * @return Returns 0 for success, or a negative error code value for failure.
179  */
180 int32_t ocs_hal_rqpair_tow_cmd_process(ocs_hal_t *hal, hal_cq_t *cq, uint8_t *cqe)
181 {
182  /* Seems silly to call a SLI function to decode - use the structure directly for performance */
184  uint16_t rq_id;
185  uint32_t index;
186  int32_t rqindex;
187  int32_t rq_status;
188  uint32_t h_len;
189  uint32_t p_len;
190  ocs_hal_sequence_t *seq;
191  uint8_t tow_lock_taken = 0;
192 #if defined(OCS_DISC_SPIN_DELAY)
193  uint32_t delay = 0;
194  char prop_buf[32];
195 #endif
196 
197  rq_status = sli_fc_rqe_rqid_and_index(&hal->sli, cqe, &rq_id, &index);
198  if (0 != rq_status) {
199  switch (rq_status) {
202  /* just get RQ buffer then return to chip */
203  rqindex = ocs_hal_rqpair_find(hal, rq_id);
204  if (rqindex < 0) {
205  ocs_log_err(hal->os, "status=%#x: rq_id lookup failed for id=%#x\n",
206  rq_status, rq_id);
207  break;
208  }
209 
210  /* get RQ buffer */
211  seq = ocs_hal_rqpair_get(hal, rqindex, index);
212 
213  /* return to chip */
214  if (ocs_hal_rqpair_sequence_free(hal, seq)) {
215  ocs_log_err(hal->os, "status=%#x, failed to return buffers to RQ\n",
216  rq_status);
217  break;
218  }
219  break;
222  /* since RQ buffers were not consumed, cannot return them to chip */
223  ocs_log_debug(hal->os, "Warning: RCQE status=%#x, \n", rq_status);
224  /* fall through */
225  default:
226  break;
227  }
228  return -1;
229  }
230 
231  rqindex = ocs_hal_rqpair_find(hal, rq_id);
232  if (rqindex < 0) {
233  ocs_log_err(hal->os, "Error: rq_id lookup failed for id=%#x\n", rq_id);
234  return -1;
235  }
236 
237  OCS_STAT({ hal_rq_t *rq = hal->hal_rq[hal->hal_rq_lookup[rqindex]]; rq->use_count++; rq->hdr_use_count++;
238  rq->payload_use_count++;})
239 
240  seq = ocs_hal_rqpair_get(hal, rqindex, index);
241  ocs_hal_assert(seq != NULL);
242 
243  seq->hal = hal;
244  seq->tow = opt_wr->tow;
245  seq->tow_oox = opt_wr->oox;
246  seq->xri = opt_wr->xri;
247  seq->hio = NULL;
248 
249  sli_fc_rqe_length(&hal->sli, cqe, &h_len, &p_len);
250  seq->header->dma.len = h_len;
251  seq->payload->dma.len = p_len;
252  seq->fcfi = sli_fc_rqe_fcfi(&hal->sli, cqe);
253  seq->hal_priv = cq->eq;
254 
255  if (seq->tow) {
256  fc_header_t *fc_hdr = seq->header->dma.virt;
257 
258  seq->hio = ocs_hal_io_lookup(hal, seq->xri);
259  ocs_lock(&seq->hio->tow_lock);
260  tow_lock_taken = 1;
261 
262  /* save the FCFI, src_id, dest_id and ox_id because we need it for the sequence object when the data comes. */
263  seq->hio->tow_buf->fcfi = seq->fcfi;
264  seq->hio->tow_buf->hdr.ox_id = fc_hdr->ox_id;
265  seq->hio->tow_buf->hdr.s_id = fc_hdr->s_id;
266  seq->hio->tow_buf->hdr.d_id = fc_hdr->d_id;
267  seq->hio->tow_buf->cmd_cqe = 1;
268 
269  /*
270  * Since optimized write has been done for this IO, then clear the sequence
271  * initiative bit in the header so that the upper layers wait for the
272  * data. This should flow exactly like the first burst case.
273  */
275 
276  /* If TOW CMD CQE came before previous TRSP CQE of same XRI */
277  if (seq->hio->type == OCS_HAL_IO_TARGET_RSP) {
278  seq->hio->tow_buf->call_tow_cmd = TRUE;
279  seq->hio->tow_buf->cmd_seq = seq;
280  goto exit;
281  }
282  }
283 
284  /* bounce enabled, single RQ, we snoop the ox_id to choose the cpuidx */
285  if (hal->config.bounce) {
286  fc_header_t *hdr = seq->header->dma.virt;
287  uint32_t s_id = fc_be24toh(hdr->s_id);
288  uint32_t d_id = fc_be24toh(hdr->d_id);
289  uint32_t ox_id = ocs_be16toh(hdr->ox_id);
290  if (hal->callback.bounce != NULL) {
291  (*hal->callback.bounce)(ocs_hal_unsol_process_bounce, seq, s_id, d_id, ox_id);
292  }
293  } else {
294  hal->callback.unsolicited(hal->args.unsolicited, seq);
295  }
296 
297  if (seq->tow) {
298  /* If data cqe came before cmd cqe in out of order in case of TOW */
299  if(seq->hio->tow_buf->data_cqe == 1) {
300 
301 #if defined(OCS_DISC_SPIN_DELAY)
302  if (ocs_get_property("disk_spin_delay", prop_buf, sizeof(prop_buf)) == 0) {
303  delay = ocs_strtoul(prop_buf, 0, 0);
304  ocs_delay_usec(delay);
305  }
306 #endif
307  /* bounce enabled, single RQ, we snoop the ox_id to choose the cpuidx */
308  if (hal->config.bounce) {
309  fc_header_t *hdr = seq->header->dma.virt;
310  uint32_t s_id = fc_be24toh(hdr->s_id);
311  uint32_t d_id = fc_be24toh(hdr->d_id);
312  uint32_t ox_id = ocs_be16toh(hdr->ox_id);
313  if (hal->callback.bounce != NULL) {
314  (*hal->callback.bounce)(ocs_hal_unsol_process_bounce,
315  &seq->hio->tow_buf->seq, s_id, d_id, ox_id);
316  }
317  } else {
318  hal->callback.unsolicited(hal->args.unsolicited, &seq->hio->tow_buf->seq);
319  }
320  }
321  }
322 
323 exit:
324  if(tow_lock_taken) {
325  ocs_unlock(&seq->hio->tow_lock);
326  }
327  return 0;
328 }
329 
330 /**
331  * @brief Process CQ completions for Auto xfer rdy data phases.
332  *
333  * @par Description
334  * The data is DMA'd into the data buffer posted to the SGL prior to the XRI
335  * being assigned to an IO. When the completion is received, All of the data
336  * is in the single buffer.
337  *
338  * @param hal Hardware context.
339  * @param cq Pointer to HAL completion queue.
340  * @param cqe Completion queue entry.
341  *
342  * @return Returns 0 for success, or a negative error code value for failure.
343  */
344 int32_t ocs_hal_rqpair_tow_data_process(ocs_hal_t *hal, hal_cq_t *cq, uint8_t *cqe)
345 {
346  /* Seems silly to call a SLI function to decode - use the structure directly for performance */
348  ocs_hal_sequence_t *seq;
349  ocs_hal_io_t *io;
351 #if defined(OCS_DISC_SPIN_DELAY)
352  uint32_t delay = 0;
353  char prop_buf[32];
354 #endif
355  /* Look up the IO */
356  io = ocs_hal_io_lookup(hal, opt_wr->xri);
357  ocs_lock(&io->tow_lock);
358  buf = io->tow_buf;
359  buf->data_cqe = 1;
360  seq = &buf->seq;
361  seq->hal = hal;
362  seq->tow = TRUE;
363  seq->tow_oox = 0;
364  seq->xri = opt_wr->xri;
365  seq->hio = io;
366  seq->header = &buf->header;
367  seq->payload = &buf->payload;
368 
369  seq->header->dma.len = sizeof(fc_header_t);
370  seq->payload->dma.len = opt_wr->total_data_placed;
371  seq->fcfi = buf->fcfi;
372  seq->hal_priv = cq->eq;
373 
374  if (opt_wr->status == SLI4_FC_WCQE_STATUS_SUCCESS) {
376  } else if (opt_wr->status == SLI4_FC_WCQE_STATUS_REMOTE_STOP) {
378  } else {
380  }
381 
382  /* If TOW CMD CQE came before previous TRSP CQE of same XRI */
383  if(io->type == OCS_HAL_IO_TARGET_RSP) {
384  io->tow_buf->call_tow_data = TRUE;
385  goto exit;
386  }
387 
388  if(!buf->cmd_cqe) {
389  /* if data cqe came before cmd cqe, return here, cmd cqe will handle */
390  goto exit;
391  }
392 
393 #if defined(OCS_DISC_SPIN_DELAY)
394  if (ocs_get_property("disk_spin_delay", prop_buf, sizeof(prop_buf)) == 0) {
395  delay = ocs_strtoul(prop_buf, 0, 0);
396  ocs_delay_usec(delay);
397  }
398 #endif
399 
400  /* bounce enabled, single RQ, we snoop the ox_id to choose the cpuidx */
401  if (hal->config.bounce) {
402  fc_header_t *hdr = seq->header->dma.virt;
403  uint32_t s_id = fc_be24toh(hdr->s_id);
404  uint32_t d_id = fc_be24toh(hdr->d_id);
405  uint32_t ox_id = ocs_be16toh(hdr->ox_id);
406  if (hal->callback.bounce != NULL) {
407  (*hal->callback.bounce)(ocs_hal_unsol_process_bounce, seq, s_id, d_id, ox_id);
408  }
409  } else {
410  hal->callback.unsolicited(hal->args.unsolicited, seq);
411  }
412 
413 exit:
414  ocs_unlock(&io->tow_lock);
415  return 0;
416 }
417 
418 /**
419  * @brief Return pointer to RQ buffer entry.
420  *
421  * @par Description
422  * Returns a pointer to the RQ buffer entry given by @c rqindex and @c bufindex.
423  *
424  * @param hal Hardware context.
425  * @param rqindex Index of the RQ that is being processed.
426  * @param bufindex Index into the RQ that is being processed.
427  *
428  * @return Pointer to the sequence structure, or NULL otherwise.
429  */
430 static ocs_hal_sequence_t *
431 ocs_hal_rqpair_get(ocs_hal_t *hal, uint16_t rqindex, uint16_t bufindex)
432 {
433  sli4_queue_t *rq_hdr = hal->rq[rqindex];
434  ocs_hal_sequence_t *seq = NULL;
435  hal_rq_t *rq = hal->hal_rq[hal->hal_rq_lookup[rqindex]];
436 
437 #if defined(ENABLE_DEBUG_RQBUF)
438  sli4_queue_t *rq_payload = hal->rq[rqindex+1];
439  uint64_t rqbuf_debug_value = 0xdead0000 | ((rq->id & 0xf) << 12) | (bufindex & 0xfff);
440 #endif
441 
442  if (bufindex >= rq_hdr->length) {
443  ocs_log_err(hal->os, "RQ index %d bufindex %d exceed ring length %d for id %d\n",
444  rqindex, bufindex, rq_hdr->length, rq_hdr->id);
445  return NULL;
446  }
447 
448  /* rq_hdr lock also covers rqindex+1 queue */
449  sli_queue_lock(rq_hdr);
450 
451 #if defined(ENABLE_DEBUG_RQBUF)
452  /* Put a debug value into the rq, to track which entries are still valid */
453  _sli_queue_poke(&hal->sli, rq_hdr, bufindex, (uint8_t *)&rqbuf_debug_value);
454  _sli_queue_poke(&hal->sli, rq_payload, bufindex, (uint8_t *)&rqbuf_debug_value);
455 #endif
456 
457  seq = rq->rq_tracker[bufindex];
458  rq->rq_tracker[bufindex] = NULL;
459 
460  if (seq == NULL ) {
461  ocs_log_err(hal->os, "RQ buffer NULL, rqindex %d, bufindex %d, current q index = %d\n",
462  rqindex, bufindex, rq_hdr->index);
463  }
464 
465  sli_queue_unlock(rq_hdr);
466  return seq;
467 }
468 
469 /**
470  * @brief Posts an RQ buffer to a queue and update the verification structures
471  *
472  * @param hal hardware context
473  * @param seq Pointer to sequence object.
474  *
475  * @return Returns 0 on success, or a non-zero value otherwise.
476  */
477 static int32_t
479 {
480  sli4_queue_t *rq_hdr = hal->rq[seq->header->rqindex];
481  sli4_queue_t *rq_payload = hal->rq[seq->payload->rqindex];
482  uint32_t hal_rq_index = hal->hal_rq_lookup[seq->header->rqindex];
483  hal_rq_t *rq = hal->hal_rq[hal_rq_index];
484  uint32_t phys_hdr[2];
485  uint32_t phys_payload[2];
486  int32_t qindex_hdr;
487  int32_t qindex_payload;
488 
489  /* Update the RQ verification lookup tables */
490  phys_hdr[0] = ocs_addr32_hi(seq->header->dma.phys);
491  phys_hdr[1] = ocs_addr32_lo(seq->header->dma.phys);
492  phys_payload[0] = ocs_addr32_hi(seq->payload->dma.phys);
493  phys_payload[1] = ocs_addr32_lo(seq->payload->dma.phys);
494 
495  /* rq_hdr lock also covers payload / header->rqindex+1 queue */
496  sli_queue_lock(rq_hdr);
497 
498  /*
499  * Note: The header must be posted last for buffer pair mode because
500  * posting on the header queue posts the payload queue as well.
501  * We do not ring the payload queue independently in RQ pair mode.
502  */
503  qindex_payload = _sli_queue_write(&hal->sli, rq_payload, (void *)phys_payload);
504  qindex_hdr = _sli_queue_write(&hal->sli, rq_hdr, (void *)phys_hdr);
505  if (qindex_hdr < 0 ||
506  qindex_payload < 0) {
507  ocs_log_err(hal->os, "RQ_ID=%#x write failed\n", rq_hdr->id);
508  sli_queue_unlock(rq_hdr);
509  return OCS_HAL_RTN_ERROR;
510  }
511 
512  /* ensure the indexes are the same */
513  ocs_hal_assert(qindex_hdr == qindex_payload);
514 
515  /* Update the lookup table */
516  if (rq->rq_tracker[qindex_hdr] == NULL) {
517  rq->rq_tracker[qindex_hdr] = seq;
518  } else {
519  ocs_log_test(hal->os, "expected rq_tracker[%d][%d] buffer to be NULL\n",
520  hal_rq_index, qindex_hdr);
521  }
522 
523  sli_queue_unlock(rq_hdr);
524  return OCS_HAL_RTN_SUCCESS;
525 }
526 
527 /**
528  * @brief Return RQ buffers (while in RQ pair mode).
529  *
530  * @par Description
531  * The header and payload buffers are returned to the Receive Queue.
532  *
533  * @param hal Hardware context.
534  * @param seq Header/payload sequence buffers.
535  *
536  * @return Returns OCS_HAL_RTN_SUCCESS on success, or an error code value on failure.
537  */
538 
541 {
543 
544  /* TOW sequences has a dummy index */
547  }
548 
549  /*
550  * Post the data buffer first. Because in RQ pair mode, ringing the
551  * doorbell of the header ring will post the data buffer as well.
552  */
553  if (ocs_hal_rqpair_put(hal, seq)) {
554  ocs_log_err(hal->os, "error writing buffers\n");
555  return OCS_HAL_RTN_ERROR;
556  }
557 
558  return rc;
559 }
560 
561 /**
562  * @brief Find the RQ index of RQ_ID.
563  *
564  * @param hal Hardware context.
565  * @param rq_id RQ ID to find.
566  *
567  * @return Returns the RQ index, or -1 if not found
568  */
569 static inline int32_t
570 ocs_hal_rqpair_find(ocs_hal_t *hal, uint16_t rq_id)
571 {
572  return ocs_hal_queue_hash_find(hal->rq_hash, rq_id);
573 }
574 
575 /**
576  * @ingroup devInitShutdown
577  * @brief Allocate tow buffers.
578  *
579  * @par Description
580  * Allocates the tow buffers and places them on the free list.
581  *
582  * @param hal Hardware context allocated by the caller.
583  * @param num_buffers Number of buffers to allocate.
584  *
585  * @return Returns 0 on success, or a non-zero value on failure.
586  */
587 ocs_hal_rtn_e ocs_hal_rqpair_tow_buffer_alloc(ocs_hal_t *hal, uint32_t num_buffers)
588 {
590  uint32_t i;
591 
592  hal->tow_buffer_pool = ocs_pool_alloc(hal->os, sizeof(ocs_hal_tow_buffer_t),
593  num_buffers, FALSE);
594  if (!hal->tow_buffer_pool) {
595  ocs_log_err(hal->os, "Failed to allocate tow buffer pool\n");
596  return OCS_HAL_RTN_NO_MEMORY;
597  }
598 
599  for (i = 0; i < num_buffers; i++) {
600  /* Allocate the wrapper object */
601  buf = ocs_pool_get_instance(hal->tow_buffer_pool, i);
602  ocs_hal_assert(buf);
603 
604  /* Allocate the tow dma buffer */
605  if (ocs_dma_alloc(hal->os, &buf->payload.dma, hal->config.tow_io_size,
606  OCS_MIN_DMA_ALIGNMENT)) {
607  ocs_log_err(hal->os, "Failed to allocate dma buffer\n");
608  return OCS_HAL_RTN_NO_MEMORY;
609  }
610 
611  /* build a fake data header in big endian */
613  buf->hdr.r_ctl = FC_RCTL_FC4_DATA;
614  buf->hdr.type = FC_TYPE_FCP;
620 
621  /* build the fake header DMA object */
623  buf->header.dma.virt = &buf->hdr;
624  buf->header.dma.alloc = buf;
625  buf->header.dma.size = sizeof(buf->hdr);
626  buf->header.dma.len = sizeof(buf->hdr);
627 
629  }
630 
631  ocs_log_info(hal->os, "Allocated tow buffer pool\n");
632  return OCS_HAL_RTN_SUCCESS;
633 }
634 
635 /**
636  * @ingroup devInitShutdown
637  * @brief Post Auto xfer rdy buffers to the XRIs posted with DNRX.
638  *
639  * @par Description
640  * When new buffers are freed, check existing XRIs waiting for buffers.
641  *
642  * @param hal Hardware context allocated by the caller.
643  */
644 static void ocs_hal_rqpair_tow_dnrx_check(ocs_hal_t *hal)
645 {
646  ocs_hal_io_t *io;
647  int32_t rc;
648 
649  ocs_lock(&hal->io_lock);
650 
651  while (!ocs_list_empty(&hal->io_port_dnrx)) {
652  io = ocs_list_remove_head(&hal->io_port_dnrx);
653  rc = ocs_hal_reque_xri(hal, io);
654  if(rc) {
655  break;
656  }
657  }
658 
659  ocs_unlock(&hal->io_lock);
660 }
661 
662 /**
663  * @brief Called when the POST_SGL_PAGE command completes.
664  *
665  * @par Description
666  * Free the mailbox command buffer.
667  *
668  * @param hal Hardware context.
669  * @param status Status field from the mbox completion.
670  * @param mqe Mailbox response structure.
671  * @param arg Pointer to a callback function that signals the caller that the command is done.
672  *
673  * @return Returns 0.
674  */
675 static int32_t
676 ocs_hal_rqpair_auto_xfer_rdy_move_to_port_cb(ocs_hal_t *hal, int32_t status, uint8_t *mqe, void *arg)
677 {
678  ocs_free(hal->os, mqe, SLI4_BMBX_SIZE);
679  return 0;
680 }
681 
682 /**
683  * @brief Prepares an XRI to move to the chip.
684  *
685  * @par Description
686  * Puts the data SGL into the SGL list for the IO object and possibly registers
687  * an SGL list for the XRI. Since both the POST_XRI and POST_SGL_PAGES commands are
688  * mailbox commands, we don't need to wait for completion before preceding.
689  *
690  * @param hal Hardware context allocated by the caller.
691  * @param io Pointer to the IO object.
692  *
693  * @return Returns OCS_HAL_RTN_SUCCESS for success, or an error code value for failure.
694  */
695 ocs_hal_rtn_e ocs_hal_rqpair_tow_move_to_port(ocs_hal_t *hal, ocs_hal_io_t *io)
696 {
697  uint16_t sgl_buf_length = sizeof(sli4_req_fcoe_post_sgl_pages_t) +
699 
700  /* We only need to preregister the SGL if it has not yet been done. */
701  if (!sli_get_sgl_preregister(&hal->sli)) {
702  uint8_t *post_sgl;
703  ocs_dma_t *psgls = &io->def_sgl;
704  ocs_dma_t **sgls = &psgls;
705 
706  /* non-local buffer required for mailbox queue */
707  post_sgl = ocs_malloc(hal->os, sgl_buf_length, OCS_M_NOWAIT);
708  if (post_sgl == NULL) {
709  ocs_log_err(hal->os, "no buffer for command\n");
710  return OCS_HAL_RTN_NO_MEMORY;
711  }
712 
713  sli_cmd_fcoe_post_sgl_pages(&hal->sli, post_sgl, sgl_buf_length,
714  io->indicator, 1, sgls, NULL, NULL);
715  if (ocs_hal_command(hal, post_sgl, OCS_CMD_NOWAIT,
717  ocs_free(hal->os, post_sgl, SLI4_BMBX_SIZE);
718  return OCS_HAL_RTN_ERROR;
719  }
720  }
721 
722  ocs_lock(&hal->io_lock);
723  if (ocs_hal_rqpair_tow_xri_buffer_attach(hal, io, FALSE) != 0) { /* DNRX set - no buffer */
724  ocs_unlock(&hal->io_lock);
725  return OCS_HAL_RTN_ERROR;
726  }
727  ocs_unlock(&hal->io_lock);
728 
729  return OCS_HAL_RTN_SUCCESS;
730 }
731 
732 /**
733  * @brief Prepares an XRI to move back to the host.
734  *
735  * @par Description
736  * Releases any attached buffer back to the pool.
737  *
738  * @param hal Hardware context allocated by the caller.
739  * @param io Pointer to the IO object.
740  */
741 void ocs_hal_rqpair_tow_move_to_host(ocs_hal_t *hal, ocs_hal_io_t *io)
742 {
743  if (io->tow_buf != NULL) {
744  ocs_lock(&hal->io_lock);
745  /* check list and remove if there */
746  if (ocs_list_on_list(&io->dnrx_link)) {
747  ocs_list_remove(&hal->io_port_dnrx, io);
748  io->tow_dnrx = 0;
749  /* release the count for waiting for a buffer */
750  ocs_hal_io_free(hal, io);
751  }
752 
753  ocs_pool_put(hal->tow_buffer_pool, io->tow_buf);
754  io->tow_buf = NULL;
755  ocs_unlock(&hal->io_lock);
756 
758  }
759  return;
760 }
761 
762 /**
763  * @brief Attach an TOW XRI buffer to an IO
764  *
765  * @par Description
766  * Puts the data SGL into the SGL list for the IO object
767  * @n @name
768  * @b Note: io_lock must be held.
769  *
770  * @param hal Hardware context allocated by the caller.
771  * @param io Pointer to the IO object.
772  *
773  * @return Returns the value of DNRX bit in the TRSP and ABORT WQEs.
774  */
775 uint8_t ocs_hal_rqpair_tow_xri_buffer_attach(ocs_hal_t *hal, ocs_hal_io_t *io, int32_t reuse_buf)
776 {
778  sli4_sge_t *data;
779 
780  if(!reuse_buf) {
781  buf = ocs_pool_get(hal->tow_buffer_pool);
782  io->tow_buf = buf;
783  }
784 
785  data = io->def_sgl.virt;
786  data[0].sge_type = SLI4_SGE_TYPE_SKIP;
787  data[0].last = 0;
788 
789  /*
790  * Note: if we are doing DIF assists, then the SGE[1] must contain the
791  * DI_SEED SGE. The host is responsible for programming:
792  * SGE Type (Word 2, bits 30:27)
793  * Replacement App Tag (Word 2 bits 15:0)
794  * App Tag (Word 3 bits 15:0)
795  * New Ref Tag (Word 3 bit 23)
796  * Metadata Enable (Word 3 bit 20)
797  * Auto-Increment RefTag (Word 3 bit 19)
798  * Block Size (Word 3 bits 18:16)
799  * The following fields are managed by the SLI Port:
800  * Ref Tag Compare (Word 0)
801  * Replacement Ref Tag (Word 1) - In not the LBA
802  * NA (Word 2 bit 25)
803  * Opcode RX (Word 3 bits 27:24)
804  * Checksum Enable (Word 3 bit 22)
805  * RefTag Enable (Word 3 bit 21)
806  *
807  * The first two SGLs are cleared by ocs_hal_io_init_sges(), so assume eveything is cleared.
808  */
809  if (hal->config.tow_p_type) {
810  sli4_diseed_sge_t *diseed = (sli4_diseed_sge_t*)&data[1];
811 
812  diseed->sge_type = SLI4_SGE_TYPE_DISEED;
813  diseed->repl_app_tag = hal->config.tow_app_tag_value;
814  diseed->app_tag_cmp = hal->config.tow_app_tag_value;
815  diseed->check_app_tag = hal->config.tow_app_tag_valid;
816  diseed->auto_incr_ref_tag = TRUE; /* Always the LBA */
817  diseed->dif_blk_size = hal->config.tow_blksize_chip;
818  } else {
819  data[1].sge_type = SLI4_SGE_TYPE_SKIP;
820  data[1].last = 0;
821  }
822 
823  data[2].sge_type = SLI4_SGE_TYPE_DATA;
824  data[2].buffer_address_high = ocs_addr32_hi(io->tow_buf->payload.dma.phys);
825  data[2].buffer_address_low = ocs_addr32_lo(io->tow_buf->payload.dma.phys);
826  data[2].buffer_length = io->tow_buf->payload.dma.size;
827  data[2].last = TRUE;
828  data[3].sge_type = SLI4_SGE_TYPE_SKIP;
829 
830  return 0;
831 }
832 
833 /**
834  * @brief Return tow buffers (while in RQ pair mode).
835  *
836  * @par Description
837  * The header and payload buffers are returned to the tow pool.
838  *
839  * @param hal Hardware context.
840  * @param seq Header/payload sequence buffers.
841  *
842  * @return Returns OCS_HAL_RTN_SUCCESS for success, an error code value for failure.
843  */
845 {
846  ocs_hal_tow_buffer_t *buf = seq->header->dma.alloc;
847  buf->data_cqe = 0;
848  buf->cmd_cqe = 0;
849  buf->fcfi = 0;
850  buf->call_tow_cmd = FALSE;
851  buf->call_tow_data = FALSE;
852 
853  /* build a fake data header in big endian */
855  buf->hdr.r_ctl = FC_RCTL_FC4_DATA;
856  buf->hdr.type = FC_TYPE_FCP;
862 
863  /* build the fake header DMA object */
865  buf->header.dma.virt = &buf->hdr;
866  buf->header.dma.alloc = buf;
867  buf->header.dma.size = sizeof(buf->hdr);
868  buf->header.dma.len = sizeof(buf->hdr);
870 
872  return OCS_HAL_RTN_SUCCESS;
873 }
874 
875 /**
876  * @ingroup devInitShutdown
877  * @brief Free tow buffers.
878  *
879  * @par Description
880  * Frees the tow buffers.
881  *
882  * @param hal Hardware context allocated by the caller.
883  *
884  * @return Returns 0 on success, or a non-zero value on failure.
885  */
886 static void ocs_hal_rqpair_tow_buffer_free(ocs_hal_t *hal)
887 {
889  uint32_t i;
890 
891  if (hal->tow_buffer_pool != NULL) {
892  ocs_lock(&hal->io_lock);
893  for (i = 0; i < ocs_pool_get_count(hal->tow_buffer_pool); i++) {
894  buf = ocs_pool_get_instance(hal->tow_buffer_pool, i);
895  if (buf != NULL) {
896  ocs_dma_free(hal->os, &buf->payload.dma);
897  }
898  }
899  ocs_unlock(&hal->io_lock);
900 
901  ocs_pool_free(hal->tow_buffer_pool);
902  hal->tow_buffer_pool = NULL;
903  }
904 }
905 
906 /**
907  * @ingroup devInitShutdown
908  * @brief Configure the rq_pair function from ocs_hal_init().
909  * Must be after the IOs are setup and the state is active
910  *
911  * @par Description
912  * Allocates the TOW buffers and posts initial XRIs for this feature.
913  *
914  * @param hal Hardware context allocated by the caller.
915  *
916  * @return Returns 0 on success, or a non-zero value on failure.
917  */
919 {
920  ocs_hal_rtn_e rc = 0;
921  uint32_t xris_posted;
922 
923  /*
924  * If we get this far, the auto TOW feature was enabled successfully,
925  * otherwise ocs_hal_init() would return with an error.
926  * So allocate the buffers based on the initial XRI pool required to support this feature.
927  */
928  if (hal->tow_enabled) {
929  if (hal->tow_buffer_pool == NULL) {
930  /*
931  * Allocate one more buffer than XRIs so that when all the XRIs are in use, we still have
932  * one to post back for the case where the response phase is started in the context of
933  * the data completion.
934  */
935  rc = ocs_hal_rqpair_tow_buffer_alloc(hal, hal->config.tow_xri_cnt + 1);
936  if (rc != OCS_HAL_RTN_SUCCESS) {
937  goto exit_err;
938  }
939  } else {
940  ocs_pool_reset(hal->tow_buffer_pool);
941  }
942 
943  /* Post the XRIs */
944  xris_posted = ocs_hal_xri_move_to_port_owned(hal, hal->config.tow_xri_cnt);
945  if (xris_posted != hal->config.tow_xri_cnt) {
946  ocs_log_err(hal->os, "Post xri failed, only posted %d XRIs\n", xris_posted);
947  rc = OCS_HAL_RTN_ERROR;
948  goto exit_err;
949  }
950  }
951 
952  ocs_log_debug(hal->os, "RQ pair init completed\n");
953 exit_err:
954  return rc;
955 }
956 
957 /**
958  * @ingroup devInitShutdown
959  * @brief Tear down the rq_pair function from ocs_hal_teardown().
960  *
961  * @par Description
962  * Frees the buffers to TOW buffers.
963  *
964  * @param hal Hardware context allocated by the caller.
965  */
966 void
967 ocs_hal_rqpair_teardown(ocs_hal_t *hal)
968 {
969  /* We need to free any tow buffers */
971 }
ocs_hal_rtn_e ocs_hal_rqpair_init(ocs_hal_t *hal)
Configure the rq_pair function from ocs_hal_init(). Must be after the IOs are setup and the state is ...
uint32_t sge_type
Definition: sli4.h:501
uint32_t buffer_length
Definition: sli4.h:504
uint32_t r_ctl
Definition: ocs_fcp.h:158
int32_t ocs_hal_io_free(ocs_hal_t *hal, ocs_hal_io_t *io)
Free a previously-allocated HAL IO object.
Definition: ocs_hal.c:4001
static int32_t ocs_hal_rqpair_auto_xfer_rdy_move_to_port_cb(ocs_hal_t *hal, int32_t status, uint8_t *mqe, void *arg)
Called when the POST_SGL_PAGE command completes.
#define SLI4_FC_WCQE_STATUS_REMOTE_STOP
Definition: sli4_fc.h:1640
static int32_t ocs_list_on_list(ocs_list_link_t *link)
Test if object is on a list.
Definition: ocs_list.h:460
ocs_hal_rq_buffer_t payload
Definition: ocs_hal.h:818
void ocs_hal_rqpair_tow_move_to_host(ocs_hal_t *hal, ocs_hal_io_t *io)
Prepares an XRI to move back to the host.
void * ocs_pool_get(ocs_pool_t *pool)
Allocate a memory pool item.
Definition: ocs_pool.c:197
static ocs_hal_sequence_t * ocs_hal_rqpair_get(ocs_hal_t *hal, uint16_t rqindex, uint16_t bufindex)
Return pointer to RQ buffer entry.
ocs_hal_rtn_e ocs_hal_rqpair_tow_buffer_alloc(ocs_hal_t *hal, uint32_t num_buffers)
Allocate tow buffers.
ocs_hal_rq_buffer_t * header
Definition: ocs_hal.h:790
static int32_t ocs_list_empty(ocs_list_t *list)
Test if a list is empty.
Definition: ocs_list.h:125
int32_t ocs_hal_rqpair_process_rq(ocs_hal_t *hal, hal_cq_t *cq, uint8_t *cqe)
Process receive queue completions for RQ Pair mode.
#define FC_FCTL_SEQUENCE_INITIATIVE
Definition: ocs_fcp.h:233
void ocs_pool_put(ocs_pool_t *pool, void *item)
free memory pool item
Definition: ocs_pool.c:230
#define SLI4_CQE_CODE_MARKER
Definition: sli4_fc.h:1896
uint32_t dif_blk_size
Definition: sli4.h:546
uint8_t call_tow_cmd
Definition: ocs_hal.h:827
T10 DIF Seed Scatter-Gather Entry (SGE)
Definition: sli4.h:529
FCOE_POST_SGL_PAGES.
Definition: sli4_fc.h:155
static void sli_queue_lock(sli4_queue_t *q)
Definition: sli4.h:3487
ocs_hal_rq_buffer_t header
Definition: ocs_hal.h:817
uint32_t index
Definition: sli4.h:3452
uint32_t ox_id
Definition: ocs_fcp.h:168
ocs_hal_rtn_e
Definition: ocs_hal.h:159
ocs_hal_io_t * hio
Definition: ocs_hal.h:796
int32_t ocs_hal_reque_xri(ocs_hal_t *hal, ocs_hal_io_t *io)
Reque XRI.
Definition: ocs_hal.c:13528
#define FC_TYPE_FCP
Definition: ocs_fcp.h:56
#define SLI4_SGE_TYPE_DISEED
Definition: sli4.h:595
#define SLI4_FC_ASYNC_RQ_INSUFF_BUF_FRM_DISC
Definition: sli4_fc.h:1793
uint32_t sge_type
Definition: sli4.h:533
static uint32_t fc_htobe24(uint32_t x)
Definition: ocs_fcp.h:147
int32_t ocs_hal_queue_hash_find(ocs_queue_hash_t *hash, uint16_t id)
Find index given queue ID.
Definition: ocs_hal.c:9564
fc_header_t hdr
Definition: ocs_hal.h:816
uint32_t repl_app_tag
Definition: sli4.h:533
uint32_t check_app_tag
Definition: sli4.h:546
ocs_pool_t * ocs_pool_alloc(ocs_os_handle_t os, uint32_t size, uint32_t count, uint32_t use_lock)
Allocate a memory pool.
Definition: ocs_pool.c:88
void ocs_pool_free(ocs_pool_t *pool)
Free a previously allocated memory pool.
Definition: ocs_pool.c:173
#define FC_FCTL_END_SEQUENCE
Definition: ocs_fcp.h:230
#define SLI4_FC_WCQE_STATUS_SUCCESS
FC/FCoE Completion Status Codes.
Definition: sli4_fc.h:1638
static void * ocs_list_remove(ocs_list_t *list, void *item)
Remove an item from the list.
Definition: ocs_list.h:385
ocs_hal_io_t * ocs_hal_io_lookup(ocs_hal_t *hal, uint32_t xri)
Find IO given indicator (xri).
Definition: ocs_hal.c:11213
uint8_t tow_oox
Definition: ocs_hal.h:789
uint8_t ocs_hal_rqpair_tow_xri_buffer_attach(ocs_hal_t *hal, ocs_hal_io_t *io, int reuse_buf)
uint8_t call_tow_data
Definition: ocs_hal.h:828
#define SLI4_BMBX_SIZE
Definition: sli4.h:150
#define OCS_HAL_RQ_INDEX_DUMMY_HDR
Structure to track optimized write buffers posted to chip owned XRIs.
Definition: ocs_hal.h:813
uint32_t d_id
Definition: ocs_fcp.h:158
FC header in big-endian order.
Definition: ocs_fcp.h:157
uint16_t rqindex
Definition: ocs_hal.h:327
#define SLI4_FC_ASYNC_RQ_INSUFF_BUF_NEEDED
Definition: sli4_fc.h:1792
static int32_t ocs_hal_rqpair_find(ocs_hal_t *hal, uint16_t rq_id)
Find the RQ index of RQ_ID.
static ocs_hal_rtn_e ocs_hal_rqpair_tow_buffer_sequence_reset(ocs_hal_t *hal, ocs_hal_sequence_t *seq)
Return tow buffers (while in RQ pair mode).
#define SLI4_FC_ASYNC_RQ_BUF_LEN_EXCEEDED
Definition: sli4_fc.h:1791
static uint32_t sli_get_sgl_preregister(sli4_t *sli4)
Definition: sli4.h:3977
#define SLI4_FC_ASYNC_RQ_DMA_FAILURE
Definition: sli4_fc.h:1794
static void ocs_hal_rqpair_tow_dnrx_check(ocs_hal_t *hal)
Post Auto xfer rdy buffers to the XRIs posted with DNRX.
#define SLI4_CQE_CODE_OFFSET
Definition: sli4_fc.h:1884
uint16_t length
Definition: sli4.h:3454
uint16_t id
Definition: sli4.h:3456
ocs_hal_t * hal
Definition: ocs_hal.h:785
void * ocs_pool_get_instance(ocs_pool_t *pool, uint32_t idx)
Return item given an index.
Definition: ocs_pool.c:315
#define OCS_STAT(x)
Definition: ocs_stats.h:46
void ocs_pool_reset(ocs_pool_t *pool)
Reset a memory pool.
Definition: ocs_pool.c:131
Definition: sli4_fc.h:162
ocs_hal_rtn_e ocs_hal_rqpair_tow_move_to_port(ocs_hal_t *hal, ocs_hal_io_t *io)
Prepares an XRI to move to the chip.
uint32_t auto_incr_ref_tag
Definition: sli4.h:546
int32_t sli_cmd_fcoe_post_sgl_pages(sli4_t *sli4, void *buf, size_t size, uint16_t xri, uint32_t xri_count, ocs_dma_t *page0[], ocs_dma_t *page1[], ocs_dma_t *dma)
Write an FCOE_POST_SGL_PAGES command.
Definition: sli4_fc.c:276
uint32_t f_ctl
Definition: ocs_fcp.h:163
static void sli_queue_unlock(sli4_queue_t *q)
Definition: sli4.h:3493
#define FC_FCTL_EXCHANGE_RESPONDER
Definition: ocs_fcp.h:226
ocs_hal_unsol_status_e status
Definition: ocs_hal.h:794
void ocs_hal_unsol_process_bounce(void *arg)
Definition: ocs_hal.c:2518
uint32_t ocs_hal_xri_move_to_port_owned(ocs_hal_t *hal, uint32_t num_xri)
Move XRIs from the host-controlled pool to the port.
Definition: ocs_hal.c:12921
#define ocs_list_remove_head(list)
Remove and return an item from the head of the list.
Definition: ocs_list.h:374
uint32_t xri
Definition: ocs_hal.h:795
static int32_t sli_fc_rqe_length(sli4_t *sli4, void *cqe, uint32_t *len_hdr, uint32_t *len_data)
Retrieve the received header and payload length.
Definition: sli4_fc.h:1959
uint32_t buffer_address_low
Definition: sli4.h:500
#define SLI4_SGE_TYPE_DATA
Definition: sli4.h:589
uint32_t app_tag_cmp
Definition: sli4.h:546
Defines a general FC sequence object, consisting of a header, payload buffers and a HAL IO in the cas...
Definition: ocs_hal.h:784
int32_t _sli_queue_poke(sli4_t *sli4, sli4_queue_t *q, uint32_t index, uint8_t *entry)
Definition: sli4.c:5813
#define ocs_hal_assert(cond)
Definition: ocs_hal.h:82
int32_t ocs_hal_rqpair_tow_data_process(ocs_hal_t *hal, hal_cq_t *cq, uint8_t *cqe)
Process CQ completions for Auto xfer rdy data phases.
static uint8_t sli_fc_rqe_fcfi(sli4_t *sli4, void *cqe)
Retrieve the received FCFI.
Definition: sli4_fc.h:1984
ocs_dma_t dma
Definition: ocs_hal.h:328
uint32_t last
Definition: sli4.h:501
uint32_t info
Definition: ocs_fcp.h:158
int32_t ocs_hal_rqpair_tow_cmd_process(ocs_hal_t *hal, hal_cq_t *cq, uint8_t *cqe)
Process receive queue completions for RQ Pair mode - Auto xfer rdy.
uint32_t type
Definition: ocs_fcp.h:163
uint32_t buffer_address_high
Definition: sli4.h:499
#define FC_FCTL_FIRST_SEQUENCE
Definition: ocs_fcp.h:228
int32_t ocs_get_property(const char *prop_name, char *buffer, uint32_t buffer_len)
get driver wide property value
#define FC_RCTL_FC4_DATA
Definition: ocs_fcp.h:213
static int32_t ocs_hal_rqpair_put(ocs_hal_t *hal, ocs_hal_sequence_t *seq)
Posts an RQ buffer to a queue and update the verification structures.
Scatter-Gather Entry (SGE)
Definition: sli4.h:497
ocs_hal_rtn_e ocs_hal_rqpair_sequence_free(ocs_hal_t *hal, ocs_hal_sequence_t *seq)
Return RQ buffers (while in RQ pair mode).
ocs_hal_rtn_e ocs_hal_command(ocs_hal_t *hal, uint8_t *cmd, uint32_t opts, void *cb, void *arg)
Issue a SLI command.
Definition: ocs_hal.c:2731
static uint32_t fc_be24toh(uint32_t x)
Definition: ocs_fcp.h:143
static void ocs_hal_rqpair_tow_buffer_free(ocs_hal_t *hal)
Free tow buffers.
#define SLI4_SGE_TYPE_SKIP
Definition: sli4.h:598
ocs_hal_sequence_t seq
Definition: ocs_hal.h:819
uint32_t s_id
Definition: ocs_fcp.h:161
void ocs_hal_rqpair_teardown(ocs_hal_t *hal)
Tear down the rq_pair function from ocs_hal_teardown().
#define OCS_HAL_RQ_INDEX_DUMMY_DATA
Definition: ocs_hal.h:814
#define FC_RCTL_INFO_SOL_DATA
Definition: ocs_fcp.h:218
uint32_t ocs_pool_get_count(ocs_pool_t *pool)
Return memory pool item count.
Definition: ocs_pool.c:291
int32_t _sli_queue_write(sli4_t *sli4, sli4_queue_t *q, uint8_t *entry)
Write an entry to the queue object.
Definition: sli4.c:5565
ocs_hal_rq_buffer_t * payload
Definition: ocs_hal.h:791
int32_t sli_fc_rqe_rqid_and_index(sli4_t *sli4, uint8_t *cqe, uint16_t *rq_id, uint32_t *index)
Retrieve the RQ index from the completion.
Definition: sli4_fc.c:2768
#define FC_FCTL_LAST_SEQUENCE
Definition: ocs_fcp.h:229