Emulex Logo
OneCoreā„¢ Storage SDK Release 11.2
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
sli4_skh_iscsi.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  * Implementation of iSCSI Skyhawk SLI-4 functions
36  */
37 
38 #include "ocs.h"
39 #include "ocs_hal.h"
40 #include "sli4.h"
41 #include "sli4_iscsi.h"
42 #include "ocs_iscsi_spec.h"
43 
44 #if defined(OCS_INCLUDE_DEBUG)
45 #include "ocs_debug.h"
46 #endif
47 
48 extern const char *SLI_QNAME[];
49 
50 static int32_t sli_skh_iscsi_cqe_i_sol(sli4_t *, uint8_t *cqe,
51  sli4_qentry_fields_t *fields);
52 static int32_t sli_skh_iscsi_cqe_t_sol(sli4_t *, uint8_t *cqe,
53  sli4_qentry_fields_t *fields);
54 static int32_t sli_skh_iscsi_cqe_t_sol_data_digest(sli4_t *, uint8_t *cqe,
55  sli4_qentry_fields_t *fields);
56 static int32_t sli_skh_iscsi_cqe_t_cnxinv(sli4_t *, uint8_t *cqe,
57  sli4_qentry_fields_t *fields);
58 static int32_t sli_skh_iscsi_cqe_t_cmdinv(sli4_t *, uint8_t *cqe,
59  sli4_qentry_fields_t *fields);
60 static int32_t sli_skh_iscsi_cqe_i_t_dpdu(sli4_t *, uint8_t *cqe,
61  sli4_qentry_fields_t *fields);
62 static int32_t sli_skh_iscsi_cqe_i_t_dmsg(sli4_t *, uint8_t *cqe,
63  sli4_qentry_fields_t *fields);
64 static int32_t sli_skh_iscsi_cqe_tx_dif_error(sli4_t *sli4, uint8_t *cqe,
65  sli4_qentry_fields_t *fields);
66 
67 /*
68  * Determine the CQE format based on the "code" in the common format
69  */
71 {
72  sli_skh_iscsi_cqe_t_cnxinv, /* 0 dummy - should not occur */
73  sli_skh_iscsi_cqe_i_sol, /* 1 NORMAL*/
74  sli_skh_iscsi_cqe_i_sol, /* 2 CMD_DIGEST_ERROR */
75  sli_skh_iscsi_cqe_i_sol, /* 3 RECV_PDU_DSL_ERROR */
76  sli_skh_iscsi_cqe_i_sol, /* 4 RECV_SEQ_BURST_ERROR */
77  sli_skh_iscsi_cqe_i_sol, /* 5 RECV_AHS_NOT_SUPPORTED */
78  sli_skh_iscsi_cqe_i_sol, /* 6 HDR_DIGEST_ERROR */
79  sli_skh_iscsi_cqe_i_sol, /* 7 OPCODE_ERROR */
80  sli_skh_iscsi_cqe_i_sol, /* 8 ITT_TTT_WRONG_CXN */
81  sli_skh_iscsi_cqe_i_sol, /* 9 ITT_TTT_TOO_BIG */
82  sli_skh_iscsi_cqe_i_sol, /* A TCP_RECV_RST */
83  sli_skh_iscsi_cqe_i_sol, /* B TCP_TIMEOUT */
84  sli_skh_iscsi_cqe_i_sol, /* C TCP_SENT_RST */
85  sli_skh_iscsi_cqe_i_sol, /* D TCP_RECV_FIN */
86  sli_skh_iscsi_cqe_i_sol, /* E BAD_UNSOL_PDU */
87  sli_skh_iscsi_cqe_i_sol, /* F BAD_WQE_INDEX */
88  sli_skh_iscsi_cqe_i_sol, /* 10 RESIDUAL_OVERRUN */
89  sli_skh_iscsi_cqe_i_sol, /* 11 RESIDUAL_UNDERRUN */
90  sli_skh_iscsi_cqe_i_sol, /* 12 INVALID_STATSN */
91  sli_skh_iscsi_cqe_i_sol, /* 13 R2T_INVALID_FIELDS */
92  sli_skh_iscsi_cqe_i_sol, /* 14 INVALID_LUN */
93  sli_skh_iscsi_cqe_i_sol, /* 15 INVALID_ICD_STATE */
94  sli_skh_iscsi_cqe_i_sol, /* 16 RECV_PDU_INVALID_ITT */
95  sli_skh_iscsi_cqe_i_sol, /* 17 RECV_SEQ_BUF_OUT_OF_ORDER */
96  sli_skh_iscsi_cqe_i_sol, /* 18 RECV_PDU_INVALID_DATASN */
97  sli_skh_iscsi_cqe_t_cnxinv, /* 19 HOST_CXN_INVALIDATION */
98  sli_skh_iscsi_cqe_t_cnxinv, /* 1A HOST_CXN_INVL_WITH_PDU */
99  sli_skh_iscsi_cqe_t_cmdinv, /* 1B HOST_CMD_INVALIDATION */
100  sli_skh_iscsi_cqe_i_t_dpdu, /* 1C UNSOL_HDR_NOTIFY */
101  sli_skh_iscsi_cqe_i_t_dpdu, /* 1D UNSOL_DATA_NOTIFY */
102  sli_skh_iscsi_cqe_i_t_dpdu, /* 1E UNSOL_DATA_DIGEST_ERROR */
103  sli_skh_iscsi_cqe_i_t_dmsg, /* 1F TCP_ACK */
104  sli_skh_iscsi_cqe_t_cnxinv, /* 20 CMD_DATA_DIFF_CXN */
105  sli_skh_iscsi_cqe_t_cnxinv, /* 21 DIF_ERROR */
106  sli_skh_iscsi_cqe_t_cnxinv /* 22 RECV_UNSOL_PDU_ERROR */
107 };
108 
110 {
111  sli_skh_iscsi_cqe_t_cnxinv, /* 0 dummy - should not occur */
112  sli_skh_iscsi_cqe_t_sol, /* 1 NORMAL*/
113  sli_skh_iscsi_cqe_t_sol_data_digest, /* 2 CMD_DIGEST_ERROR */
114  sli_skh_iscsi_cqe_t_cnxinv, /* 3 RECV_PDU_DSL_ERROR */
115  sli_skh_iscsi_cqe_t_cnxinv, /* 4 RECV_SEQ_BURST_ERROR */
116  sli_skh_iscsi_cqe_t_cnxinv, /* 5 RECV_AHS_NOT_SUPPORTED */
117  sli_skh_iscsi_cqe_t_cnxinv, /* 6 HDR_DIGEST_ERROR */
118  sli_skh_iscsi_cqe_t_cnxinv, /* 7 OPCODE_ERROR */
119  sli_skh_iscsi_cqe_t_cnxinv, /* 8 ITT_TTT_WRONG_CXN */
120  sli_skh_iscsi_cqe_t_cnxinv, /* 9 ITT_TTT_TOO_BIG */
121  sli_skh_iscsi_cqe_t_cnxinv, /* A TCP_RECV_RST */
122  sli_skh_iscsi_cqe_t_cnxinv, /* B TCP_TIMEOUT */
123  sli_skh_iscsi_cqe_t_cnxinv, /* C TCP_SENT_RST */
124  sli_skh_iscsi_cqe_t_cnxinv, /* D TCP_RECV_FIN */
125  sli_skh_iscsi_cqe_t_cnxinv, /* E BAD_UNSOL_PDU */
126  sli_skh_iscsi_cqe_t_cnxinv, /* F BAD_WQE_INDEX */
127  sli_skh_iscsi_cqe_t_cnxinv, /* 10 RESIDUAL_OVERRUN */
128  sli_skh_iscsi_cqe_t_cnxinv, /* 11 RESIDUAL_UNDERRUN */
129  sli_skh_iscsi_cqe_t_cmdinv, /* 12 INVALID_STATSN */
130  sli_skh_iscsi_cqe_t_cmdinv, /* 13 R2T_INVALID_FIELDS */
131  sli_skh_iscsi_cqe_t_cmdinv, /* 14 INVALID_LUN */
132  sli_skh_iscsi_cqe_t_cmdinv, /* 15 INVALID_ICD_STATE */
133  sli_skh_iscsi_cqe_t_cmdinv, /* 16 RECV_PDU_INVALID_ITT */
134  sli_skh_iscsi_cqe_t_cmdinv, /* 17 RECV_SEQ_BUF_OUT_OF_ORDER */
135  sli_skh_iscsi_cqe_t_cmdinv, /* 18 RECV_PDU_INVALID_DATASN */
136  sli_skh_iscsi_cqe_t_cnxinv, /* 19 HOST_CXN_INVALIDATION */
137  sli_skh_iscsi_cqe_t_cnxinv, /* 1A HOST_CXN_INVL_WITH_PDU */
138  sli_skh_iscsi_cqe_t_cmdinv, /* 1B HOST_CMD_INVALIDATION */
139  sli_skh_iscsi_cqe_i_t_dpdu, /* 1C UNSOL_HDR_NOTIFY */
140  sli_skh_iscsi_cqe_i_t_dpdu, /* 1D UNSOL_DATA_NOTIFY */
141  sli_skh_iscsi_cqe_i_t_dpdu, /* 1E UNSOL_DATA_DIGEST_ERROR */
142  sli_skh_iscsi_cqe_i_t_dmsg, /* 1F TCP_ACK */
143  sli_skh_iscsi_cqe_t_cnxinv, /* 20 CMD_DATA_DIFF_CXN */
144  sli_skh_iscsi_cqe_t_cnxinv, /* 21 DIF_ERROR */
145  sli_skh_iscsi_cqe_t_cnxinv, /* 22 RECV_UNSOL_PDU_ERROR */
146  sli_skh_iscsi_cqe_tx_dif_error /* 23 TX_DIF_ERR */
147 };
148 
149 /**
150  * @brief Write an DIF WQE work queue entry.
151  *
152  * @param buf Destination buffer for the WQE.
153  * @param dif_info Pointer to the DIF fields (may be NULL).
154  * @param sgl0 Pointer to the SGL to put in SGE0 (data).
155  * @param sgl_dif Pointer to the SGL to put in SGE1 (DIF separate).
156  *
157  * @return Returns 0 on success, or a non-zero value otherwise.
158  */
159 static int32_t
160 sli_skh_wqe_dif(void *buf,
161  ocs_hal_dif_info_t* dif_info,
162  sli4_sge_t *sgl0,
163  sli4_sge_t *sgl_dif)
164 {
165  sli4_skh_wqe_dif_t * req = buf;
166 
167  if (sgl0 != NULL) {
168  req->sge0_addr_high = sgl0->buffer_address_high;
169  req->sge0_addr_low = sgl0->buffer_address_low;
170  req->s0l = sgl0->last;
171  req->sge0_offset = sgl0->data_offset;
172  req->sge0_length = sgl0->buffer_length;
173  }
174 
175  if (dif_info->dif_separate) {
176  req->sdm = 1;
177  if (sgl_dif != NULL) {
178  req->mkaddr_addr_high = sgl_dif->buffer_address_high;
179  req->mkaddr_addr_low = sgl_dif->buffer_address_low;
180  }
181  }
182 
183  req->dif_enable = 1;
184  req->exp_ref_tag = dif_info->ref_tag_cmp;
185  req->t10_crc_seed = 0;
186  req->t10_atrt = dif_info->disable_app_ref_ffff;
187  req->t10_at = dif_info->disable_app_ffff;
188  req->rep_ref_tag = dif_info->ref_tag_repl;
189  req->meta_tag = dif_info->app_tag_cmp;
190  req->dif_blk_size = dif_info->blk_size;
191  req->dif_auto_inc = dif_info->auto_incr_ref_tag;
192  req->check_meta_tag = dif_info->check_app_tag;
193  req->check_ref_tag = dif_info->check_ref_tag;
194  req->check_crc = dif_info->check_guard;
195  req->replace_ref_tag = dif_info->repl_ref_tag;
196 
197  switch(dif_info->dif_oper) {
201  break;
205  break;
209  break;
210  default:
211  break;
212  }
213 
214  return 0;
215 }
216 
217 
218 /**
219  * @brief write an INITIATOR_WRITE_COMMAND WQE work queue entry
220  *
221  * @par Description
222  * - sgl[0] points the BHS.
223  * - sgl[1] must be empty.
224  * - sgl[2] starts the data SGEs.
225  *
226  * @param sli4 SLI context.
227  * @param buf Destination buffer for the WQE.
228  * @param size Buffer size in bytes.
229  * @param lun LUN value for the command.
230  * @param exp_xfer_len Total # of payload bytes.
231  * @param cmdsn iSCSI cmdsn for the command.
232  * @param icd_index ICD index fr this request.
233  * @param dif_info Pointer to the DIF fields (may be NULL).
234  * @param sgl Pointer to the SGEs for this IO.
235  * @param n_sge Number of SGEs present.
236  *
237  * @return Returns 0 on success, or a non-zero value otherwise.
238  */
239 static int32_t
240 sli_skh_wqe_ini_write(sli4_t *sli4, void *buf, size_t size,
241  uint16_t lun,
242  uint32_t exp_xfer_len,
243  uint32_t cmdsn,
244  uint16_t icd_index,
245  ocs_hal_dif_info_t* dif_info,
246  sli4_sge_t *sgl,
247  uint32_t n_sge)
248 {
249  sli4_skh_wqe_ini_write_t * req = buf;
250 
251  /* TODO: Replace memset & optimize as 90% data is inited.
252  */
253  ocs_memset(buf, 0, size);
254  req->type = SLI4_WQE_INI_WRITE;
255  req->lun = lun & 0xffff;
256  req->dsp = (exp_xfer_len > 0 ? 1 : 0);
257  req->exp_xfer_len = exp_xfer_len;
258  req->icd_index = icd_index;
259  req->bhs_addr_high = sgl[0].buffer_address_high;
260  req->bhs_addr_low = sgl[0].buffer_address_low;
261  req->cmdsn = cmdsn;
262 
263  /* Optimization: Providing multiple SGE frags embedded in WQE
264  * for achieving better metrics for smaller sized io ops.
265  */
266  if (dif_info == NULL) {
267  if (n_sge > 2) {
268  req->sge0_addr_high = sgl[2].buffer_address_high;
269  req->sge0_addr_low = sgl[2].buffer_address_low;
270  req->s0l = sgl[2].last;
271  req->sge0_offset = sgl[2].data_offset;
272  req->sge0_length = sgl[2].buffer_length;
273  }
274 
275  if (n_sge > 3) {
276  req->sge1_addr_high = sgl[3].buffer_address_high;
277  req->sge1_addr_low = sgl[3].buffer_address_low;
278  req->s1l = sgl[3].last;
279  req->sge1_offset = sgl[3].data_offset;
280  req->sge1_length = sgl[3].buffer_length;
281  }
282  } else {
283  /*
284  * For initiator WQEs, the BHS is first, followed by a skip,
285  * next is the DIF seed, DIF (if separate) and then data.
286  */
287  sli4_sge_t *sgl_data = NULL;
288  sli4_sge_t *sgl_dif = NULL;
289 
290  if (dif_info->dif_separate) {
291  sgl_dif = (n_sge > 3 ? &sgl[3] : NULL);
292  sgl_data = (n_sge > 4 ? &sgl[4] : NULL);
293  } else {
294  sgl_data = (n_sge > 3 ? &sgl[3] : NULL);
295  }
296  sli_skh_wqe_dif(buf, dif_info, sgl_data, sgl_dif);
297  }
298 
299  return 0;
300 }
301 
302 /**
303  * @brief Write an INITIATOR_TMF WQE work queue entry.
304  *
305  * @par Description
306  * - sgl[0] points the the BHS.
307  *
308  * @param sli4 SLI context.
309  * @param buf Destination buffer for the WQE.
310  * @param size Buffer size in bytes.
311  * @param lun The LUN value for the command.
312  * @param cmdsn iSCSI cmdsn for the command.
313  * @param icd_index ICD index fr this request.
314  * @param sgl Pointer to the SGEs for this IO.
315  * @param n_sge Number of SGEs present.
316  *
317  * @return Returns 0 on success, or a non-zero value otherwise.
318  */
319 static int32_t
320 sli_skh_wqe_ini_tmf(sli4_t *sli4, void *buf, size_t size,
321  uint16_t lun,
322  uint32_t cmdsn,
323  uint16_t icd_index,
324  sli4_sge_t *sgl,
325  uint32_t n_sge)
326 {
327  sli4_skh_wqe_ini_tmf_t * req = buf;
328 
329  ocs_memset(buf, 0, size);
330 
331  req->type = SLI4_WQE_INI_TMF;
332  req->lun = lun & 0xffff;
333  req->icd_index = icd_index;
334  req->bhs_addr_high = sgl[0].buffer_address_high;
335  req->bhs_addr_low = sgl[0].buffer_address_low;
336  req->cmdsn = cmdsn;
337 
338  return 0;
339 }
340 
341 
342 /**
343  * @brief Write an INITIATOR_NOP_OUT_COMMAND WQE work queue entry.
344  *
345  * @param sli4 SLI context.
346  * @param buf Destination buffer for the WQE.
347  * @param size Buffer size in bytes.
348  * @param dm Determines whether a dmsg CQE is generated.
349  * @param cmdsn iSCSI cmdsn for the command.
350  * @param bhs Pointer to the basic header segment.
351  * @param payload1 Optional pointer to payload memory.
352  * @param payload2 Optional pointer to payload memory.
353  * @param exp_xfer_len Total # of payload bytes.
354  * @param icd_index ICD index fr this request.
355  *
356  * @return Returns 0 on success, or a non-zero value otherwise.
357  */
358 static int32_t
359 sli_skh_wqe_ini_nop(sli4_t *sli4, void *buf, size_t size,
360  uint8_t dm,
361  uint32_t cmdsn,
362  ocs_dma_t *bhs,
363  ocs_dma_t *payload1,
364  ocs_dma_t *payload2,
365  uint32_t exp_xfer_len,
366  uint16_t icd_index)
367 {
368  sli4_skh_wqe_ini_nop_t *req = buf;
369 
370  /* TODO: Replace memset & optimize as 90% data is inited.
371  */
372  ocs_memset(buf, 0, size);
373 
374  req->type = SLI4_WQE_INI_NOP;
375  req->dsp = (exp_xfer_len > 0 ? 1 : 0);
376  req->dm = dm;
377  req->exp_xfer_len = exp_xfer_len;
378  req->icd_index = icd_index;
379  req->bhs_addr_high = ocs_addr32_hi(bhs->phys);
380  req->bhs_addr_low = ocs_addr32_lo(bhs->phys);
381  req->cmdsn = cmdsn;
382 
383  if (exp_xfer_len > 0 && payload1 != NULL) {
384  req->sge0_addr_high = ocs_addr32_hi(payload1->phys);
385  req->sge0_addr_low = ocs_addr32_lo(payload1->phys);
386  req->s0l = (payload2 == NULL ? 1 : 0);
387  req->sge0_offset = 0;
388  req->sge0_length = (payload2 != NULL ? payload1->size : exp_xfer_len);
389  }
390 
391  if (exp_xfer_len > 0 && payload1 != NULL && payload2 != NULL) {
392  req->sge1_addr_high = ocs_addr32_hi(payload2->phys);
393  req->sge1_addr_low = ocs_addr32_lo(payload2->phys);
394  req->s1l = 1;
395  req->sge1_offset = payload1->size;
396  req->sge1_length = exp_xfer_len - payload1->size;
397  }
398 
399  return 0;
400 }
401 
402 /**
403  * @brief write an INITIATOR_READ WQE work queue entry.
404  *
405  * @par Description
406  * - sgl[0] points the the BHS.
407  * - sgl[1] must be empty.
408  * - sgl[2] starts the data SGEs.
409  *
410  * @param sli4 SLI context.
411  * @param buf Destination buffer for the WQE.
412  * @param size Buffer size in bytes.
413  * @param lun LUN value for the command.
414  * @param exp_xfer_len Total # of payload bytes.
415  * @param cmdsn iSCSI cmdsn for the command.
416  * @param icd_index ICD index fr this request.
417  * @param dif_info Pointer to the DIF fields (may be NULL).
418  * @param sgl Pointer to the SGEs for this IO.
419  * @param n_sge Number of SGEs present.
420  *
421  * @return Returns 0 on success, or a non-zero value otherwise.
422  */
423 static int32_t
424 sli_skh_wqe_ini_read(sli4_t *sli4, void *buf, size_t size,
425  uint16_t lun,
426  uint32_t exp_xfer_len,
427  uint32_t cmdsn,
428  uint16_t icd_index,
429  ocs_hal_dif_info_t* dif_info,
430  sli4_sge_t *sgl,
431  uint32_t n_sge)
432 {
433  sli4_skh_wqe_ini_read_t *req = buf;
434 
435  /* TODO: Replace memset & optimize as 90% data is inited.
436  */
437  ocs_memset(buf, 0, size);
438 
439  req->type = SLI4_WQE_INI_READ;
440  req->lun = lun & 0xffff;
441  req->exp_xfer_len = exp_xfer_len;
442  req->icd_index = icd_index;
443  req->bhs_addr_high = sgl[0].buffer_address_high;
444  req->bhs_addr_low = sgl[0].buffer_address_low;
445  req->cmdsn = cmdsn;
446 
447  if (dif_info == NULL) {
448  if (n_sge > 2) {
449  req->sge0_addr_high = sgl[2].buffer_address_high;
450  req->sge0_addr_low = sgl[2].buffer_address_low;
451  req->s0l = sgl[2].last;
452  req->sge0_offset = sgl[2].data_offset;
453  req->sge0_length = sgl[2].buffer_length;
454  }
455 
456  if (n_sge > 3) {
457  req->sge1_addr_high = sgl[3].buffer_address_high;
458  req->sge1_addr_low = sgl[3].buffer_address_low;
459  req->s1l = sgl[3].last;
460  req->sge1_offset = sgl[3].data_offset;
461  req->sge1_length = sgl[3].buffer_length;
462  }
463  } else {
464  /*
465  * For initiator WQEs, the BHS is first, followed by a skip,
466  * next is the DIF seed, DIF (if separate) and then data.
467  */
468  sli4_sge_t *sgl_data = NULL;
469  sli4_sge_t *sgl_dif = NULL;
470 
471  if (dif_info->dif_separate) {
472  sgl_dif = (n_sge > 3 ? &sgl[3] : NULL);
473  sgl_data = (n_sge > 4 ? &sgl[4] : NULL);
474  } else {
475  sgl_data = (n_sge > 3 ? &sgl[3] : NULL);
476  }
477  sli_skh_wqe_dif(buf, dif_info, sgl_data, sgl_dif);
478  }
479 
480  return 0;
481 }
482 
483 //@@@TODO: For skyhawk context update wqe, address ppdu, sgl chaining
484 // bits appropriately.
485 /**
486  * @brief Write an CONTEXT_UPDATE_WQE work queue entry
487  *
488  * @param sli4 SLI context.
489  * @param buf destination buffer for the WQE.
490  * @param size buffer size in bytes.
491  * @param lgn_options the target login options for the connection.
492  * @param statsn the status SN for the connection.
493  *
494  * @return Returns 0 on success, or a non-zero value otherwise.
495  */
496 static int32_t
497 sli_skh_wqe_update_context(sli4_t *sli4, void *buf, size_t size,
498  ocs_hal_target_login_options_t *lgn_options,
499  uint32_t statsn)
500 {
501  sli4_skh_wqe_context_update_t * req = buf;
502 
503  ocs_memset(buf, 0, size);
504 
506  req->max_burst = lgn_options->session_options.max_burst;
507  req->max_send_dsl = lgn_options->max_send_dsl;
508  req->first_burst = lgn_options->session_options.first_burst;
509  req->max_r2t = lgn_options->session_options.max_r2t;
510  req->header_digest_enable = lgn_options->hdr_digest;
511  req->data_digest_enable = lgn_options->data_digest;
513  req->immediate_data = lgn_options->session_options.immediate_data;
514  req->initial_r2t = lgn_options->session_options.initial_r2t;
515  req->statsn = statsn;
516  req->max_recv_dsl = lgn_options->max_rcv_dsl;
517  req->max_cxns = lgn_options->session_options.max_connections;
518  req->dm = 1;
521 
522  return 0;
523 }
524 
525 /**
526  * @brief Write an TGT_STS_WQE work queue entry.
527  *
528  * @param sli4 SLI context.
529  * @param buf Destination buffer for the WQE.
530  * @param size Buffer size in bytes.
531  * @param bhs Pointer to the basic header segment.
532  * @param lun LUN value for the command.
533  * @param exp_xfer_len Total # of payload bytes.
534  * @param exp_data_sn Expected data sequence number.
535  * @param itt Initiator transfer tag.
536  * @param icd_index ICD index fr this request.
537  * @param ref_icd_index Reference ICD Index.
538  * @param dif_info Pointer to the DIF fields (may be NULL).
539  * @param r2t_offset R2T buffer Offset.
540  * @param sgl Pointer to the SGEs for this IO.
541  * @param n_sge Number of SGEs present.
542  *
543  * @return Returns 0 on success, or a non-zero value otherwise.
544  */
545 static int32_t
546 sli_skh_wqe_tgt_sts(sli4_t *sli4, void *buf, size_t size,
547  ocs_dma_t *bhs,
548  uint16_t lun,
549  uint32_t exp_xfer_len,
550  uint32_t exp_data_sn,
551  uint32_t itt,
552  uint16_t icd_index,
553  uint16_t ref_icd_index,
554  ocs_hal_dif_info_t* dif_info,
555  uint32_t r2t_offset,
556  sli4_sge_t *sgl,
557  uint32_t n_sge)
558 {
559  sli4_skh_wqe_tgt_sts_t *req = buf;
560  uint32_t i;
561 
562  ocs_memset(buf, 0, size);
563 
564  req->type = SLI4_WQE_TGT_STS;
565  req->lun = lun & 0xffff;
566  req->exp_xfer_len = exp_xfer_len;
567  req->icd_index = icd_index;
568  req->exp_data_sn = exp_data_sn;
569  req->bhs_addr_high = ocs_addr32_hi(bhs->phys);
570  req->bhs_addr_low = ocs_addr32_lo(bhs->phys);
571  req->itt = itt;
572  req->ref_icd_index = ref_icd_index;
573  req->r2t_offset = r2t_offset;
574 
575  if (dif_info == NULL) {
576  req->dif_enable = 0;
577  } else {
578  sli4_sge_t *sgl_data = NULL;
579  sli4_sge_t *sgl_dif = NULL;
580 
581  if (dif_info->dif_separate) {
582  sgl_dif = (n_sge > 1 ? &sgl[1] : NULL);
583  sgl_data = (n_sge > 2 ? &sgl[2] : NULL);
584  } else {
585  sgl_data = (n_sge > 1 ? &sgl[1] : NULL);
586  }
587  sli_skh_wqe_dif(buf, dif_info, sgl_data, sgl_dif);
588  }
589 
590  /* Workaround for Skyhawk DIF issue - change all DIF and DISEED SGEs to SKIPs */
591  for (i=0; i<n_sge; i++) {
592  if ((sgl[i].sge_type == SLI4_SGE_TYPE_DIF) ||
593  (sgl[i].sge_type == SLI4_SGE_TYPE_DISEED)) {
594  sgl[i].sge_type = SLI4_SGE_TYPE_SKIP;
595  }
596  }
597 
598 
599  return 0;
600 }
601 
602 
603 /**
604  * @brief Write an TGT_DATAIN_WQE work queue entry.
605  *
606  * @par Description
607  * The SGE entries in this WQE are used if all the entries fit in the
608  * WQE for a performance increase.
609  *
610  * @param sli4 SLI context.
611  * @param buf Destination buffer for the WQE.
612  * @param size Buffer size in bytes.
613  * @param bhs Pointer to the basic header segment.
614  * @param lun LUN value for the command.
615  * @param dm Determines whether a dmsg CQE is generated.
616  * @param underrun Sets the underrun bit in the auto response.
617  * @param overrun Sets the overrun bit in the auto response.
618  * @param exp_xfer_len Total # of payload bytes.
619  * @param icd_index ICD Index for this request.
620  * @param ref_icd_index Reference ICD Index.
621  * @param data_sn Starting data sequence number.
622  * @param piggy_back_status If true, a good status is sent to the initiator.
623  * @param dif_info Pointer to the DIF fields (may be NULL).
624  * @param sgl Pointer to the SGEs for this IO.
625  * @param n_sge Number of SGEs present.
626  *
627  * @return Returns 0 on success, or a non-zero value otherwise.
628  */
629 static int32_t
630 sli_skh_wqe_tgt_datain(sli4_t *sli4, void *buf, size_t size,
631  ocs_dma_t *bhs,
632  uint16_t lun,
633  uint8_t dm,
634  uint8_t underrun,
635  uint8_t overrun,
636  uint32_t exp_xfer_len,
637  uint16_t icd_index,
638  uint16_t ref_icd_index,
639  uint32_t data_sn,
640  uint8_t piggy_back_status,
641  ocs_hal_dif_info_t* dif_info,
642  sli4_sge_t *sgl,
643  uint32_t n_sge)
644 {
645  sli4_skh_wqe_tgt_datain_t *req = buf;
646 
647  ocs_memset(buf, 0, size);
648 
649  req->type = SLI4_WQE_TGT_DATAIN;
650  req->lun = lun & 0xffff;
651  req->dsp = (exp_xfer_len > 0 ? 1 : 0);
652  req->dm = dm;
653  req->underrun = underrun;
654  req->overrun = overrun;
655  req->exp_xfer_len = exp_xfer_len;
656  req->icd_index = icd_index;
657  req->ref_icd_index = ref_icd_index;
658  req->data_sn = data_sn;
659  req->bhs_addr_high = ocs_addr32_hi(bhs->phys);
660  req->bhs_addr_low = ocs_addr32_lo(bhs->phys);
661  req->piggy_back_status = piggy_back_status;
662 
663  req->sge0_addr_high = sgl[0].buffer_address_high;
664  req->sge0_addr_low = sgl[0].buffer_address_low;
665  req->s0l = sgl[0].last;
666  req->sge0_offset = sgl[0].data_offset;
667  req->sge0_length = sgl[0].buffer_length;
668 
669  if (dif_info == NULL) {
670  if (n_sge > 1) {
671  req->sge1_addr_high = sgl[1].buffer_address_high;
672  req->sge1_addr_low = sgl[1].buffer_address_low;
673  req->s1l = sgl[1].last;
674  req->sge1_offset = sgl[1].data_offset;
675  req->sge1_length = sgl[1].buffer_length;
676  }
677  } else {
678  /*
679  * For target data in WQEs, the DIF seed is first, then
680  * DIF (if separate) and then data.
681  */
682  sli4_sge_t *sgl_data = NULL;
683  sli4_sge_t *sgl_dif = NULL;
684 
685  if (dif_info->dif_separate) {
686  sgl_dif = (n_sge > 1 ? &sgl[1] : NULL);
687  sgl_data = (n_sge > 2 ? &sgl[2] : NULL);
688  } else {
689  sgl_data = (n_sge > 1 ? &sgl[1] : NULL);
690  }
691  sli_skh_wqe_dif(buf, dif_info, sgl_data, sgl_dif);
692  }
693 
694  return 0;
695 }
696 
697 /**
698  * @brief Write an TGT_SOS_WQE work queue entry.
699  *
700  * @param sli4 SLI context.
701  * @param buf Destination buffer for the WQE.
702  * @param size Buffer size in bytes.
703  * @param bhs Pointer to the basic header segment.
704  * @param payload1 Optional pointer to payload memory.
705  * @param payload2 Optional pointer to payload memory.
706  * @param lun LUN value for the command.
707  * @param dm Determines whether a dmsg CQE is generated.
708  * @param exp_xfer_len Total # of payload bytes.
709  * @param icd_index ICD index for this request.
710  *
711  * @return Returns 0 on success, or a non-zero value otherwise.
712  */
713 static int32_t
714 sli_skh_wqe_tgt_sos(sli4_t *sli4, void *buf, size_t size,
715  ocs_dma_t *bhs,
716  ocs_dma_t *payload1,
717  ocs_dma_t *payload2,
718  uint16_t lun,
719  uint8_t dm,
720  uint32_t exp_xfer_len,
721  uint16_t icd_index)
722 {
723  sli4_skh_wqe_tgt_sos_t * req = buf;
724 
725  ocs_memset(buf, 0, size);
726 
727  req->type = SLI4_WQE_TGT_SOS;
728  req->lun = lun & 0xffff;
729  req->dsp = (exp_xfer_len > 0 ? 1 : 0);
730  req->dm = dm;
731  req->exp_xfer_len = exp_xfer_len;
732  req->icd_index = icd_index;
733  req->bhs_addr_high = ocs_addr32_hi(bhs->phys);
734  req->bhs_addr_low = ocs_addr32_lo(bhs->phys);
735  req->piggy_back_status = 1;
736 
737  if (exp_xfer_len > 0 && payload1 != NULL) {
738  req->sge0_addr_high = ocs_addr32_hi(payload1->phys);
739  req->sge0_addr_low = ocs_addr32_lo(payload1->phys);
740  req->s0l = (payload2 == NULL ? 1 : 0);
741  req->sge0_length = (payload2 != NULL ? payload1->size : exp_xfer_len);
742  }
743 
744  if (exp_xfer_len > 0 && payload1 != NULL && payload2 != NULL) {
745  req->sge1_addr_high = ocs_addr32_hi(payload2->phys);
746  req->sge1_addr_low = ocs_addr32_lo(payload2->phys);
747  req->s1l = 1;
748  req->sge1_length = exp_xfer_len - payload1->size;
749  }
750  return 0;
751 }
752 
753 
754 /**
755  * @brief Write an DM_CMD_WQE work queue entry.
756  *
757  * @param sli4 SLI context.
758  * @param buf Destination buffer for the WQE.
759  * @param size Buffer size in bytes.
760  * @param set_dm If TRUE, then a I_T_DMSG_CQE is generated on TCP ACK.
761  * @param incr_statsn If TRUE, the statsn is incremented by the FW.
762  * @param is_login If TRUE, the statsn is not updated by FW.
763  * @param bhs Pointer to the basic header segment.
764  * @param payload1 Optional pointer to payload memory.
765  * @param payload2 Optional pointer to payload memory.
766  * @param exp_xfer_len Total # of payload bytes.
767  * @param icd_index ICD index fr this request.
768  *
769  * @return Returns 0 on success, or a non-zero value otherwise.
770  */
771 static int32_t
772 sli_skh_wqe_unassisted(sli4_t *sli4, void *buf, size_t size,
773  uint8_t set_dm,
774  uint8_t incr_statsn,
775  uint8_t is_login,
776  ocs_dma_t *bhs,
777  ocs_dma_t *payload1,
778  ocs_dma_t *payload2,
779  uint32_t exp_xfer_len,
780  uint16_t icd_index)
781 {
782  sli4_skh_wqe_unassisted_t * req = buf;
783 
784  ocs_memset(buf, 0, size);
785 
786  req->type = SLI4_WQE_UNASSISTED;
787  req->dsp = (exp_xfer_len ? 1 : 0);
788  req->dm = (set_dm ? 1 : 0);
789  req->exp_xfer_len = exp_xfer_len;
790  req->icd_index = icd_index;
791  req->login_pdu = (is_login ? 1 : 0);
792  req->bhs_addr_high = ocs_addr32_hi(bhs->phys);
793  req->bhs_addr_low = ocs_addr32_lo(bhs->phys);
794  req->piggy_back_status = incr_statsn;
795 
796  if (exp_xfer_len > 0 && payload1 != NULL) {
797  req->sge0_addr_high = ocs_addr32_hi(payload1->phys);
798  req->sge0_addr_low = ocs_addr32_lo(payload1->phys);
799  req->s0l = (payload2 == NULL ? 1 : 0);
800  req->sge0_length = (payload2 != NULL ? payload1->size : exp_xfer_len);
801  }
802 
803  if (exp_xfer_len > 0 && payload1 != NULL && payload2 != NULL) {
804  req->sge1_addr_high = ocs_addr32_hi(payload2->phys);
805  req->sge1_addr_low = ocs_addr32_lo(payload2->phys);
806  req->s1l = 1;
807  req->sge1_length = exp_xfer_len - payload1->size;
808  }
809 
810  return 0;
811 }
812 
813 /**
814  * @brief Parse an iSCSI work queue CQ entry.
815  *
816  * @param sli4 SLI context.
817  * @param cqe Pointer to the CQ entry.
818  * @param fields Returns the fields embedded in the CQ entry.
819  *
820  * @return Returns 0 on success, or a non-zero value otherwise.
821  */
822 static int32_t sli_skh_iscsi_cqe_i_sol(sli4_t *sli4, uint8_t *cqe,
823  sli4_qentry_fields_t *fields)
824 {
826  uint8_t status = 0;
827  uint8_t response = 0;
828 
829  fields->ctype = SLI_CQENTRY_INI_IO;
830 
831  if (i_sol->is_sts_or_rsp) {
832  status = i_sol->status_or_response;
833  } else {
834  response = i_sol->status_or_response;
835  }
836 
837  fields->msg.isol.residual_cnt =
839  (i_sol->underrun | i_sol->overrun) ? i_sol->residual : 0);
840  fields->msg.isol.exp_cmdsn = i_sol->expcmdsn;
841  fields->msg.isol.cid = i_sol->cid;
842  fields->msg.isol.hw_status = i_sol->hw_sts;
843  fields->msg.isol.status = status;
844  fields->msg.isol.response = response;
845  //@@@TODO: flags replaced with under-run and over-run ??
846  //fields->msg.isol.flags = i_sol->flags;
847  fields->msg.isol.flags = ((i_sol->underrun << 1) |
848  (i_sol->overrun));
849  fields->msg.isol.wqe_index = i_sol->wqe_index;
850  fields->msg.isol.cmd_window = i_sol->cmd_window;
851  fields->msg.isol.code = i_sol->code;
852 
853  if (i_sol->code != ISCSI_CQE_CODE_NORMAL &&
856  ocs_log_test(sli4->os, "WQ Error: status 0x%02x\n", i_sol->code);
857  ocs_dump32(OCS_DEBUG_ALWAYS, sli4->os, "cqe", cqe,
859  }
860  i_sol->valid = 0;
861  return 0;
862 }
863 
864 /**
865  * @brief Write an QWE entry to the queue object.
866  *
867  * @param sli4 SLI context.
868  * @param q Pointer to queue object.
869  * @param entry Pointer to entry contents.
870  * @param io Pointer to the IO object.
871  *
872  * @return Returns 0 on success, or a non-zero value otherwise.
873  */
874 static int32_t
876  void *io)
877 {
878  int32_t rc = 0;
879  ocs_hal_io_t *hal_io = (ocs_hal_io_t*)io;
880  sli4_skh_wqe_unassisted_t *wqe = (void*)entry;
881  sli4_skh_wqe_unassisted_t *last_wqe_posted;
882  sli4_wqe_context_t *ctx;
883  uint32_t val = 0;
884 
885  ocs_assert(hal_io, -1);
886  ocs_lock(&q->lock);
887 
888  /* grab a free entry to see what is open */
889  ctx = ocs_list_get_head(&q->u.wq.wqe_free);
890  if (NULL != ctx) {
891  ocs_list_remove_head(&q->u.wq.wqe_free);
892  ocs_list_add_tail(&q->u.wq.wqe_busy, ctx);
893  q->u.wq.wqe_free_cnt--;
894 
895  last_wqe_posted = q->u.wq.last_wqe_posted;
896  hal_io->wq_ctx = ctx;
897  ctx->io = io;
899 
900  /* Set the tcp ACK flag as required for this WQE */
901  ctx->wait_tcp_ack = wqe->dm;
902 
903  /*
904  * Note: For target STS WQE, set the TTT based on the WRB index and
905  * the icd index.
906  *
907  * Format the TTT generated by iSCSI target
908  * |-- WRB-idx (16b) --|-- zero (4b) --|-- SGL-ICD-idx (12b) --|
909  */
910  if (wqe->type == SLI4_WQE_TGT_STS) {
911  uint32_t *dword = hal_io->bhs.virt;
912 
913  hal_io->ttt = (((uint32_t)ctx->wrb_index) << 16) | hal_io->icd;
914  dword[5] = ocs_htobe32(hal_io->ttt);
915  } else if (wqe->type == SLI4_WQE_INI_WRITE ||
916  wqe->type == SLI4_WQE_INI_TMF ||
917  wqe->type == SLI4_WQE_INI_READ) {
918  uint32_t *dword = hal_io->bhs.virt;
919 
920  hal_io->itt = (((uint32_t)ctx->wrb_index) << 16) | hal_io->icd;
921  dword[4] = ocs_htobe32(hal_io->itt);
922  } else if (wqe->type == SLI4_WQE_UNASSISTED) {
923  ocs_cxn_t *node = hal_io->node;
924  ocs_dma_t *dma = &node->login_hdr_mem;
925 
926  /* TODO: Unclean fix but works for now:
927  * In the case of TMF response io->arg is io, so just
928  * ignore lgn_mem manipulation or setting itt/cmdsn in
929  * this case.
930  */
931  if (dma->virt != NULL) {
932  uint8_t *byte = dma->virt;
933  uint32_t *dword = dma->virt;
934 
935  /* Only update the initiator NOOP/logout PDUs */
936  if ((byte[0] & 0x6F) == ISCSI_CMD_LOGOUT ||
937  (byte[0] & 0x6F) == ISCSI_CMD_NOOP) {
938  if (dword[4] != 0xFFFFFFFF) {
939  hal_io->itt = (((uint32_t)ctx->wrb_index) << 16) | hal_io->icd;
940  dword[4] = ocs_htobe32(hal_io->itt);
941  }
942  }
943  }
944  }
945 
946  /* Update wrb_index and next pointer */
947  wqe->wrb_index = ctx->wrb_index;
948  wqe->next_wqe = ctx->wrb_index;
949  if (last_wqe_posted != NULL) {
950  last_wqe_posted->next_wqe = ctx->wrb_index;
951  }
952 
953 #if defined(OCS_INCLUDE_DEBUG)
954  {
955  char desc[32];
956 
957  snprintf(desc, sizeof(desc), "%s entry %d", q->name, ctx->wrb_index);
958 
959  ocs_dump32(OCS_DEBUG_ENABLE_WQ_DUMP, sli4->os, desc, entry, q->size);
960  }
961 #endif
962  ocs_memcpy(ctx->qe, entry, q->size);
963  q->index = ctx->wrb_index; /* Needed for dump_queue */
964  q->n_posted = 1;
965  q->u.wq.last_wqe_posted = ctx->qe;
966 
967  ocs_dma_sync(&q->dma, OCS_DMASYNC_PREWRITE);
968 
969  val = SLI4_WQ_DOORBELL(q->n_posted, ctx->wrb_index, q->id);
970  ocs_reg_write32(sli4->os, q->doorbell_rset, q->doorbell_offset, val);
971  q->db_ring_cnt++;
972  q->n_posted = 0;
973  } else {
974  rc = -1;
975  }
976 
977  ocs_unlock(&q->lock);
978 
979  return rc;
980 }
981 
982 /**
983  * @brief Writes a 1 to the invalidate bit of the WQE.
984  *
985  * @param sli4 SLI context.
986  * @param q Pointer to the queue object.
987  * @param io Pointer to the IO object.
988  * @param is_for_tm TRUE if the IO is being aborted for task management,
989  * otherwise FALSE.
990  *
991  * @return Returns 0 on success, or a non-zero value otherwise.
992  */
993 static int32_t
995  uint8_t is_for_tm)
996 {
997  int32_t rc = -1;
999  sli4_wqe_context_t *ctx;
1000 
1001  /* No clean way to do this excpet to walk the active WQEs */
1002  ocs_lock(&q->lock);
1003  ctx = ocs_list_get_head(&q->u.wq.wqe_busy);
1004  while (NULL != ctx) {
1005  if (ctx->io == io) {
1006  wqe = (sli4_skh_wqe_unassisted_t *)ctx->qe;
1007  wqe->inv = 1;
1008  rc = 0;
1009 
1010  /*
1011  * If this is for Task management, then we must wait
1012  * for the TCP_ACK before issuing a completion for this
1013  * io, otherwise the FW may still be using it.
1014  */
1016  ctx->wait_tcp_ack = is_for_tm;
1017  break;
1018  }
1019  ctx = ocs_list_next(&q->u.wq.wqe_busy, ctx);
1020  }
1021 
1022  ocs_unlock(&q->lock);
1023 
1024  return rc;
1025 }
1026 
1027 /**
1028  * @brief Parse an iSCSI work queue CQ entry.
1029  *
1030  * @param sli4 SLI context.
1031  * @param cqe Pointer to the CQ entry.
1032  * @param fields Returns the fields embedded in the CQ entry.
1033  *
1034  * @return Returns 0 on success, or a non-zero value otherwise.
1035  */
1036 static int32_t sli_skh_iscsi_cqe_t_sol(sli4_t *sli4, uint8_t *cqe,
1037  sli4_qentry_fields_t *fields)
1038 {
1040 
1041  fields->ctype = SLI_CQENTRY_TGT_IO;
1042 
1043  fields->msg.tsol.hw_status = t_sol->hw_sts;
1044  fields->msg.tsol.cid = t_sol->cid;
1045  fields->msg.tsol.wqe_index = t_sol->wqe_index;
1046  fields->msg.tsol.code = t_sol->code;
1047 
1048  if (t_sol->code != ISCSI_CQE_CODE_NORMAL) {
1049  ocs_log_test(sli4->os, "WQ Error: status 0x%02x\n", t_sol->code);
1050  ocs_dump32(OCS_DEBUG_ALWAYS, sli4->os, "cqe", cqe,
1051  sizeof(sli4_skh_iscsi_t_sol_cqe_t));
1052  }
1053  t_sol->valid = 0;
1054  return 0;
1055 }
1056 
1057 /**
1058  * @brief Parse an iSCSI work queue CQ entry.
1059  *
1060  * @param sli4 SLI context.
1061  * @param cqe Pointer to the CQ entry.
1062  * @param fields Returns the fields embedded in the CQ entry.
1063  *
1064  * @return Returns 0 on success, or a non-zero value otherwise.
1065  */
1066 static int32_t sli_skh_iscsi_cqe_t_sol_data_digest(sli4_t *sli4, uint8_t *cqe,
1067  sli4_qentry_fields_t *fields)
1068 {
1069  sli4_skh_iscsi_t_sol_data_digest_cqe_t * msg = (void*)cqe;
1071 
1073 
1074  digest->buffer_offset = msg->buffer_offset;
1075  digest->exp_statsn = msg->exp_statsn;
1076  digest->cid = msg->cid;
1077  digest->datasn = msg->datasn;
1078  digest->fin = msg->fin;
1079  digest->data_seg_length = msg->data_seg_len;
1080  digest->icd_index = msg->sgl_icd_index;
1081 
1082  ocs_log_test(sli4->os, "WQ Error: status 0x%02x\n", msg->code);
1083  ocs_dump32(OCS_DEBUG_ALWAYS, sli4->os, "cqe", cqe,
1085  msg->valid = 0;
1086  return 0;
1087 }
1088 
1089 
1090 /**
1091  * @brief Parse an iSCSI work queue CQ entry.
1092  *
1093  * @param sli4 SLI context.
1094  * @param cqe Pointer to the CQ entry.
1095  * @param fields Returns the fields embedded in the CQ entry.
1096  *
1097  * @return Returns 0 on success, or a non-zero value otherwise.
1098  */
1099 static int32_t sli_skh_iscsi_cqe_t_cnxinv(sli4_t *sli4, uint8_t *cqe,
1100  sli4_qentry_fields_t *fields)
1101 {
1102  sli4_skh_iscsi_t_cnxinv_cqe_t *msg = (void*)cqe;
1103  sli4_qentry_fields_cnxinv_t *cnxinv = &fields->msg.cnxinv;
1104 
1105  fields->ctype = SLI_CQENTRY_CNX_INVALID;
1106 
1107  cnxinv->addr_high = msg->def_buf_addr_high;
1108  cnxinv->addr_low = msg->def_buf_addr_low;
1109  cnxinv->partial_data_length = msg->partial_dsl;
1110  cnxinv->cid = msg->cid;
1111  cnxinv->rq_index = msg->rq_index;
1112  cnxinv->code = msg->code;
1113 
1114  /* Mask normal things or the DVT group gets excited */
1115  if (cnxinv->code != ISCSI_CQE_CODE_TCP_RECV_FIN &&
1116  cnxinv->code != ISCSI_CQE_CODE_TCP_RECV_RST &&
1119  ocs_log_test(sli4->os, "WQ Error: status 0x%02x\n", msg->code);
1120  ocs_dump32(OCS_DEBUG_ALWAYS, sli4->os, "cqe", cqe,
1122  }
1123  msg->valid = 0;
1124  return 0;
1125 }
1126 
1127 
1128 /**
1129  * @brief Parse an iSCSI work queue CQ entry.
1130  *
1131  * @param sli4 SLI context.
1132  * @param cqe Pointer to the CQ entry.
1133  * @param fields Returns the fields embedded in the CQ entry.
1134  *
1135  * @return Returns 0 on success, or a non-zero value otherwise.
1136  */
1137 static int32_t sli_skh_iscsi_cqe_t_cmdinv(sli4_t *sli4, uint8_t *cqe,
1138  sli4_qentry_fields_t *fields)
1139 {
1140  sli4_skh_iscsi_t_cmndinv_cqe_t *msg = (void*)cqe;
1141  sli4_qentry_fields_tcmdinv_t *cmdinv = &fields->msg.tcmdinv;
1142 
1144 
1145  cmdinv->cid = msg->cid;
1146  cmdinv->icd_index = msg->sgl_icd_index;
1147  cmdinv->code = msg->code;
1148 
1149  ocs_log_test(sli4->os, "WQ Error: status 0x%02x\n", msg->code);
1150  ocs_dump32(OCS_DEBUG_ALWAYS, sli4->os, "cqe", cqe,
1152  msg->valid = 0;
1153  return 0;
1154 }
1155 
1156 
1157 /**
1158  * @brief Parse an iSCSI work queue CQ entry.
1159  *
1160  * @param sli4 SLI context.
1161  * @param cqe Pointer to the CQ entry.
1162  * @param fields Returns the fields embedded in the CQ entry.
1163  *
1164  * @return Returns 0 on success, or a non-zero value otherwise.
1165  */
1166 static int32_t sli_skh_iscsi_cqe_i_t_dpdu(sli4_t *sli4, uint8_t *cqe,
1167  sli4_qentry_fields_t *fields)
1168 {
1169  sli4_skh_iscsi_i_t_dpdu_cqe_t *msg = (void*)cqe;
1170  sli4_qentry_fields_dpdu_t *dpdu = &fields->msg.dpdu;
1171 
1172  fields->ctype = SLI_CQENTRY_RQ;
1173  dpdu->code = msg->code;
1174  dpdu->addr_high = msg->def_buf_addr_high;
1175  dpdu->addr_low = msg->def_buf_addr_low;
1176  dpdu->data_length = msg->data_length;
1177  dpdu->cid = msg->cid;
1178  dpdu->rq_index = msg->rq_index;
1179  dpdu->final = msg->fin;
1180 
1181  return 0;
1182 }
1183 
1184 
1185 /**
1186  * @brief Parse an iSCSI work queue CQ entry.
1187  *
1188  * @param sli4 SLI context.
1189  * @param cqe Pointer to the CQ entry.
1190  * @param fields Returns the fields embedded in the CQ entry.
1191  *
1192  * @return Returns 0 on success, or a non-zero value otherwise.
1193  */
1194 static int32_t sli_skh_iscsi_cqe_i_t_dmsg(sli4_t *sli4, uint8_t *cqe,
1195  sli4_qentry_fields_t *fields)
1196 {
1197  sli4_skh_iscsi_i_t_dmsg_cqe_t *msg = (void*)cqe;
1198  sli4_qentry_fields_dmsg_t *dmsg = &fields->msg.dmsg;
1199 
1200  fields->ctype = SLI_CQENTRY_TCP_ACK;
1201 
1202  dmsg->cid = msg->cid;
1203  dmsg->wqe_index = msg->wqe_index;
1204  dmsg->code = msg->code;
1205 
1206  return 0;
1207 }
1208 
1209 /**
1210  * @brief Parse an iSCSI work queue CQ entry.
1211  *
1212  * @param sli4 SLI context.
1213  * @param cqe Pointer to the CQ entry.
1214  * @param fields Returns the fields embedded in the CQ entry.
1215  *
1216  * @return Returns 0 on success, or a non-zero value otherwise.
1217  */
1218 static int32_t sli_skh_iscsi_cqe_tx_dif_error(sli4_t *sli4, uint8_t *cqe,
1219  sli4_qentry_fields_t *fields)
1220 {
1221  sli4_skh_iscsi_tx_dif_error_cqe_t *msg = (void*)cqe;
1222  sli4_qentry_fields_tx_dif_error_t *dif_err = &fields->msg.tx_dif_err;
1223 
1224  fields->ctype = SLI_CQENTRY_TX_DIF_ERROR;
1225 
1226  dif_err->dif_error = msg->dif_error;
1227  dif_err->icd_index = msg->icd_index;
1228  dif_err->cid = msg->cid;
1229 
1230  return 0;
1231 }
1232 
1233 /**
1234  * @brief Write a COMMON_GET_SLI4_PARAMETERS command to the provided buffer.
1235  *
1236  * @param sli4 SLI context pointer.
1237  * @param buf Virtual pointer to the destination buffer.
1238  * @param size Buffer size in bytes.
1239  *
1240  * @return Number of bytes written.
1241  */
1242 static int32_t
1243 sli_skh_cmd_common_get_sli4_parameters(sli4_t *sli4, void *buf, size_t size)
1244 {
1246  uint32_t cmd_off = 0;
1247  uint32_t payload_size;
1248 
1249  /* Payload length must accomodate both request and response */
1250  payload_size = max(sizeof(sli4_skh_req_common_get_sli4_parameters_t),
1252 
1253  cmd_off = sli_cmd_mailbox_queue_entry(sli4, buf, size, 0,
1254  payload_size,
1255  NULL);
1256 
1257  req = (sli4_skh_req_common_get_sli4_parameters_t*)((uint8_t*)buf + cmd_off);
1260  req->hdr.request_length = payload_size - sizeof(sli4_req_hdr_t);
1261  return cmd_off + sizeof(sli4_skh_req_common_get_sli4_parameters_t);
1262 }
1263 
1264 
1265 /**
1266  * @brief Issue the GET_SLI4_PARAMETERS IOCTL and populate the results.
1267  *
1268  * @param sli4 SLI context.
1269  *
1270  * @return Returns 0 on success, or a non-zero value otherwise.
1271  */
1272 int32_t
1274 {
1278  (((uint8_t *)sli4->bmbx.virt) + sizeof(sli4_mqe_hdr_t));
1279 
1280  if (sli_bmbx_command(sli4)) {
1281  ocs_log_crit(sli4->os, "bootstrap mailbox write fail (GET_SLI4_PARAMETERS)\n");
1282  return -1;
1283  }
1284  if (parms->hdr.status) {
1285  ocs_log_test(sli4->os, "COMMON_GET_SLI4_PARAMETERS bad status %#x\n",
1286  parms->hdr.status);
1287  return -1;
1288  }
1289 
1291  parms->eqe_count_mask);
1292 
1294  parms->cqe_count_mask);
1295 
1297  parms->mqe_count_mask);
1298 
1300  parms->wqe_count_mask);
1301 
1303  parms->rqe_count_mask);
1304 
1307  sli4->frg_num_field_mask = (1 << parms->frg_num_field_size) - 1;
1309  sli4->sgl_idx_field_mask = (1 << parms->sgl_idx_field_size) - 1;
1310  sli4->chain_sge_init_0 = parms->chain_sge_init_0;
1311  sli4->chain_sge_init_1 = parms->chain_sge_init_1;
1312  sli4->features.t10_dif_capable = parms->t10pi;
1313  sli4->features.sgl_chaining_capable = parms->sglc;
1314  sli4->features.t10_dif_inline_capable = parms->timm;
1315  sli4->features.t10_dif_separate_capable = parms->tsmm;
1316  } else {
1317  ocs_log_test(sli4->os, "bad GET_SLI4_PARAMETERS write\n");
1318  return -1;
1319  }
1320  return 0;
1321 }
1322 
1325  .wqe_ini_read = sli_skh_wqe_ini_read,
1326  .wqe_ini_write = sli_skh_wqe_ini_write,
1327  .wqe_ini_nop = sli_skh_wqe_ini_nop,
1328  .wqe_ini_tmf = sli_skh_wqe_ini_tmf,
1329  .wqe_tgt_datain = sli_skh_wqe_tgt_datain,
1330  .wqe_tgt_sts = sli_skh_wqe_tgt_sts,
1331  .wqe_tgt_sos = sli_skh_wqe_tgt_sos,
1332  .wqe_unassisted = sli_skh_wqe_unassisted,
1333  .queue_iscsi_wq_write = sli_skh_queue_iscsi_wq_write,
1334  .queue_iscsi_wqe_invalidate = sli_skh_queue_iscsi_wqe_invalidate
1335 };
1336 
1337 /* vim: set noexpandtab textwidth=120: */
uint32_t uint32_t icd_index
This structure contains the type and associated fields for a CQE completion.
Definition: sli4.h:2017
#define SLI4_WQE_INI_NOP
Definition: sli4_iscsi.h:1037
ocs_os_handle_t os
Definition: sli4.h:2202
uint32_t sge_type
Definition: sli4.h:383
uint32_t buffer_length
Definition: sli4.h:386
#define ISCSI_CQE_CODE_MAX
Definition: sli4_iscsi.h:1119
uint8_t t10_dif_separate_capable
Definition: sli4.h:2232
sli4_wqe_context_t * wq_ctx
Definition: ocs_hal.h:495
uint16_t frg_num_field_mask
Definition: sli4.h:2220
Used to decode T_SOL_DATA_DIGEST CQEs.
This structure contains the fields in a T_DATA_DIGEST completion.
Definition: sli4.h:2008
int32_t cqe_handler_t(sli4_t *, uint8_t *cqe, sli4_qentry_fields_t *fields)
Definition: sli4_iscsi.h:1279
uint32_t uint32_t sge1_addr_high
uint16_t frg_num_field_offset
Definition: sli4.h:2219
uint32_t data_offset
Definition: sli4.h:383
WQE used to for INITIATOR_TMF WQE.
uint32_t ref_tag_repl
Definition: ocs_hal.h:205
uint32_t uint32_t uint32_t uint32_t uint32_t uint32_t uint32_t uint32_t uint32_t uint32_t uint32_t rqe_count_method
uint32_t uint32_t uint32_t first_burst
uint32_t repl_ref_tag
Definition: ocs_hal.h:208
int32_t sli_cmd_mailbox_queue_entry(sli4_t *sli4, void *buf, size_t size, uint64_t tag, uint32_t length, ocs_dma_t *dma)
Write a MQE header in the provided buffer.
Definition: sli4.c:508
uint16_t size
Definition: sli4.h:2051
#define SLI4_WQE_INI_READ
Definition: sli4_iscsi.h:1038
mailbox queue Element header
Definition: sli4.h:564
uint32_t max_qentries[SLI_QTYPE_MAX]
Definition: sli4.h:2240
uint8_t * qe
Definition: sli4.h:2036
This structure contains the fields in a DMSG completion.
Definition: sli4.h:1965
static int32_t sli_skh_iscsi_cqe_t_cnxinv(sli4_t *, uint8_t *cqe, sli4_qentry_fields_t *fields)
Parse an iSCSI work queue CQ entry.
uint32_t chain_sge_init_0
Definition: sli4.h:2223
static int32_t sli_skh_wqe_unassisted(sli4_t *sli4, void *buf, size_t size, uint8_t set_dm, uint8_t incr_statsn, uint8_t is_login, ocs_dma_t *bhs, ocs_dma_t *payload1, ocs_dma_t *payload2, uint32_t exp_xfer_len, uint16_t icd_index)
Write an DM_CMD_WQE work queue entry.
Used to decode T_SOL CQEs.
uint32_t uint32_t uint32_t uint32_t uint32_t uint32_t uint32_t uint32_t uint32_t uint32_t wqe_count_mask
Used to decode DPDU CQEs.
static int32_t sli_skh_wqe_ini_read(sli4_t *sli4, void *buf, size_t size, uint16_t lun, uint32_t exp_xfer_len, uint32_t cmdsn, uint16_t icd_index, ocs_hal_dif_info_t *dif_info, sli4_sge_t *sgl, uint32_t n_sge)
write an INITIATOR_READ WQE work queue entry.
T10 DIF information passed to the transport.
Definition: ocs_hal.h:201
struct sli4_queue_t::@33::@35 wq
#define SLI4_WQE_TGT_SOS
Definition: sli4_iscsi.h:1042
cqe_handler_t * ini_skh_cqe_handlers[ISCSI_CQE_CODE_MAX+1]
uint32_t app_tag_cmp
Definition: ocs_hal.h:206
static void * ocs_list_get_head(ocs_list_t *list)
Return the first item in the list.
Definition: ocs_list.h:292
uint32_t uint32_t uint32_t uint32_t uint32_t uint32_t uint32_t uint32_t mqe_count_mask
uint32_t partial_data_length
Definition: sli4.h:1990
uint8_t tcp_ack_status
Definition: sli4.h:2039
#define ISCSI_CQE_CODE_RESIDUAL_UNDERRUN
Definition: sli4_iscsi.h:1100
Used to decode DMSG CQEs.
union sli4_qentry_fields_t::@32 msg
uint32_t uint32_t uint32_t uint32_t immediate_data
sli4_qentry_e ctype
Definition: sli4.h:2018
uint32_t uint32_t uint32_t uint32_t data_digest_enable
#define SLI4_SGE_DIF_OP_IN_CRC_OUT_NODIF
Definition: sli4.h:459
uint32_t index
Definition: sli4.h:2050
static int32_t sli_skh_iscsi_cqe_tx_dif_error(sli4_t *sli4, uint8_t *cqe, sli4_qentry_fields_t *fields)
Parse an iSCSI work queue CQ entry.
static uint32_t sli_convert_mask_to_count(uint32_t method, uint32_t mask)
Definition: sli4.h:2392
COMMON_GET_SLI4_PARAMETERS.
sli4_qentry_fields_tx_dif_error_t tx_dif_err
Definition: sli4.h:2027
#define SLI4_WQE_UNASSISTED
Definition: sli4_iscsi.h:1043
cqe_handler_t * tgt_skh_cqe_handlers[ISCSI_CQE_CODE_MAX+1]
WQE used to for INITIATOR_WRITE_COMMAND WQE (data from ini-&gt;Tgt)
uint32_t uint32_t mkaddr_addr_high
uint32_t itt
Definition: ocs_hal.h:491
#define SLI4_SGE_TYPE_DISEED
Definition: sli4.h:470
#define SLI4_SGE_TYPE_DIF
Definition: sli4.h:469
uint32_t uint32_t uint32_t uint32_t uint32_t uint32_t uint32_t uint32_t uint32_t wqe_count_method
#define ISCSI_CQE_CODE_HOST_CXN_INVL_WITH_PDU
Definition: sli4_iscsi.h:1109
struct sli4_t::@37 features
uint16_t icd
Definition: ocs_hal.h:474
uint32_t sge_supported_length
Definition: sli4.h:2248
#define SLI4_WQE_TGT_DATAIN
Definition: sli4_iscsi.h:1041
char name[8]
Definition: sli4.h:2061
uint32_t uint32_t sge1_addr_high
uint32_t dif_separate
Definition: ocs_hal.h:208
sli4_qentry_fields_tsol_t tsol
Definition: sli4.h:2022
#define ISCSI_CQE_CODE_TCP_RECV_RST
Definition: sli4_iscsi.h:1093
static int32_t sli_skh_iscsi_cqe_i_t_dpdu(sli4_t *, uint8_t *cqe, sli4_qentry_fields_t *fields)
Parse an iSCSI work queue CQ entry.
WQE used to for INITIATOR_READ WQE (data from ini-&gt;Tgt)
Used to decode CNXINV CQEs.
uint32_t uint32_t uint32_t uint32_t header_digest_enable
#define SLI4_SGE_DIF_OP_IN_CRC_OUT_CRC
Definition: sli4.h:462
#define SLI4_SGE_DIF_OP_IN_NODIF_OUT_CRC
Definition: sli4.h:458
#define ISCSI_CQE_CODE_HOST_CXN_INVALIDATION
Definition: sli4_iscsi.h:1108
uint32_t uint32_t uint32_t uint32_t uint32_t statsn
#define OCS_DEBUG_ALWAYS
Definition: ocs_debug.h:154
uint32_t ttt
Definition: ocs_hal.h:492
static int32_t sli_skh_iscsi_cqe_t_sol(sli4_t *, uint8_t *cqe, sli4_qentry_fields_t *fields)
Parse an iSCSI work queue CQ entry.
union sli4_queue_t::@33 u
uint32_t status
Definition: sli4.h:606
uint32_t doorbell_offset
Definition: sli4.h:2057
#define SLI4_WQE_TGT_STS
Definition: sli4_iscsi.h:1040
uint32_t opcode
Definition: sli4.h:584
Definition: sli4.h:2201
static int32_t sli_skh_queue_iscsi_wq_write(sli4_t *sli4, sli4_queue_t *q, uint8_t *entry, void *io)
Write an QWE entry to the queue object.
#define SLI4_BMBX_SIZE
Definition: sli4.h:128
ocs_lock_t lock
Definition: sli4.h:2049
#define SLI4_SUBSYSTEM_COMMON
Definition: sli4.h:507
sli4_qentry_fields_dpdu_t dpdu
Definition: sli4.h:2020
void ocs_dump32(uint32_t mask, ocs_os_handle_t os, const char *label, void *buf, uint32_t buf_length)
Dump 32 bit hex/ascii data.
Definition: ocs_dump32.c:72
#define ISCSI_CMD_LOGOUT
static int32_t sli_skh_wqe_ini_write(sli4_t *sli4, void *buf, size_t size, uint16_t lun, uint32_t exp_xfer_len, uint32_t cmdsn, uint16_t icd_index, ocs_hal_dif_info_t *dif_info, sli4_sge_t *sgl, uint32_t n_sge)
write an INITIATOR_WRITE_COMMAND WQE work queue entry
uint16_t sgl_idx_field_mask
Definition: sli4.h:2222
WQE used to for DIF WQE.
sli_wqe_handlers_t sli_skh_iscsi_wqe_handlers
uint32_t uint32_t uint32_t uint32_t eqe_count_mask
uint16_t sgl_idx_field_offset
Definition: sli4.h:2221
uint32_t disable_app_ffff
Definition: ocs_hal.h:208
uint32_t uint32_t sge1_addr_high
uint32_t uint32_t uint32_t uint32_t uint32_t uint32_t uint32_t mqe_count_method
static int32_t sli_skh_queue_iscsi_wqe_invalidate(sli4_t *sli4, sli4_queue_t *q, void *io, uint8_t is_for_tm)
Writes a 1 to the invalidate bit of the WQE.
#define ISCSI_CMD_NOOP
static int32_t sli_skh_iscsi_cqe_t_sol_data_digest(sli4_t *, uint8_t *cqe, sli4_qentry_fields_t *fields)
Parse an iSCSI work queue CQ entry.
uint32_t uint32_t uint32_t uint32_t uint32_t cqe_count_method
uint32_t uint32_t max_send_dsl
const char * SLI_QNAME[]
Definition: sli4.c:75
sli4_qentry_fields_isol_t isol
Definition: sli4.h:2021
static int32_t sli_skh_wqe_tgt_sts(sli4_t *sli4, void *buf, size_t size, ocs_dma_t *bhs, uint16_t lun, uint32_t exp_xfer_len, uint32_t exp_data_sn, uint32_t itt, uint16_t icd_index, uint16_t ref_icd_index, ocs_hal_dif_info_t *dif_info, uint32_t r2t_offset, sli4_sge_t *sgl, uint32_t n_sge)
Write an TGT_STS_WQE work queue entry.
sli4_qentry_fields_tcmdinv_t tcmdinv
Definition: sli4.h:2026
HAL IO object.
Definition: ocs_hal.h:471
uint16_t wrb_index
Definition: sli4.h:2037
This structure is used to track the WQEs for iSCSI.
Definition: sli4.h:2034
This structure contains the fields in a T_DATA_DIGEST completion.
Definition: sli4.h:1974
uint16_t id
Definition: sli4.h:2054
WQE used to for TGT_DATAIN WQE (data from Tgt-&gt;Ini)
This structure contains the fields in a CNXINV completion.
Definition: sli4.h:1987
#define ISCSI_CQE_CODE_RESIDUAL_OVERRUN
Definition: sli4_iscsi.h:1099
uint32_t uint32_t uint32_t uint32_t max_r2t
sli4_qentry_fields_cnxinv_t cnxinv
Definition: sli4.h:2025
Used to decode I_SOL CQEs.
int32_t(* wqe_update_context)(sli4_t *sli4, void *buf, size_t size, ocs_hal_target_login_options_t *lgn_options, uint32_t statsn)
Definition: sli4_iscsi.h:1283
ocs_cxn_t * node
Definition: ocs_hal.h:475
#define SLI4_WQE_INI_TMF
Definition: sli4_iscsi.h:1036
int32_t sli_skh_get_sli4_parameters(sli4_t *sli4)
Issue the GET_SLI4_PARAMETERS IOCTL and populate the results.
static int32_t sli_skh_wqe_tgt_sos(sli4_t *sli4, void *buf, size_t size, ocs_dma_t *bhs, ocs_dma_t *payload1, ocs_dma_t *payload2, uint16_t lun, uint8_t dm, uint32_t exp_xfer_len, uint16_t icd_index)
Write an TGT_SOS_WQE work queue entry.
uint32_t subsystem
Definition: sli4.h:584
uint32_t uint32_t uint32_t eqe_count_method
uint16_t n_posted
Definition: sli4.h:2053
sli4_qentry_fields_data_digest_t data_digest
Definition: sli4.h:2024
struct sli4_t::@38 config
static int32_t sli_skh_iscsi_cqe_i_sol(sli4_t *, uint8_t *cqe, sli4_qentry_fields_t *fields)
Parse an iSCSI work queue CQ entry.
uint16_t doorbell_rset
Definition: sli4.h:2058
Used to decode T_SOL_DATA_DIGEST CQEs.
uint32_t uint32_t uint32_t uint32_t uint32_t uint32_t cqe_count_mask
static void ocs_list_add_tail(ocs_list_t *list, void *item)
Add an item to the tail of the list.
Definition: ocs_list.h:263
uint32_t auto_incr_ref_tag
Definition: ocs_hal.h:208
uint32_t ref_tag_cmp
Definition: ocs_hal.h:204
ocs_hal_dif_oper_e dif_oper
Definition: ocs_hal.h:202
static int32_t sli_skh_iscsi_cqe_i_t_dmsg(sli4_t *, uint8_t *cqe, sli4_qentry_fields_t *fields)
Parse an iSCSI work queue CQ entry.
This structure is used to track the SLI4 queues.
Definition: sli4.h:2046
static int32_t sli_skh_wqe_dif(void *buf, ocs_hal_dif_info_t *dif_info, sli4_sge_t *sgl0, sli4_sge_t *sgl_dif)
Write an DIF WQE work queue entry.
WQE used to for INITIATOR_NOP_OUT WQE (data from ini-&gt;Tgt)
#define ocs_list_remove_head(list)
Remove and return an item from the head of the list.
Definition: ocs_list.h:374
TARGET_LOGIN_OPTIONS.
Definition: ocs_hal.h:321
uint8_t t10_dif_capable
Definition: sli4.h:2230
uint32_t buffer_address_low
Definition: sli4.h:382
Used to decode CMNDINV CQEs.
WQE used to for TGT_SOS WQE (Tgt Response)
static void * ocs_list_next(ocs_list_t *list, void *item)
Get the next item on the list.
Definition: ocs_list.h:339
uint32_t check_app_tag
Definition: ocs_hal.h:208
#define SLI4_WQE_INI_WRITE
Definition: sli4_iscsi.h:1035
static int32_t sli_skh_iscsi_cqe_t_cmdinv(sli4_t *, uint8_t *cqe, sli4_qentry_fields_t *fields)
Parse an iSCSI work queue CQ entry.
uint32_t uint32_t icd_index
ocs_dma_t bmbx
Definition: sli4.h:2262
#define ISCSI_CQE_CODE_NORMAL
Definition: sli4_iscsi.h:1084
WQE used to transmit a PDU without any modificiation (TGT_DM_CMD)
uint32_t uint32_t wqe_index
sli4_qentry_fields_dmsg_t dmsg
Definition: sli4.h:2023
#define SLI4_OPC_COMMON_GET_SLI4_PARAMETERS
Definition: sli4.h:551
This structure contains the fields in a DPDU completion.
Definition: sli4.h:1926
uint32_t last
Definition: sli4.h:383
static int32_t sli_skh_cmd_common_get_sli4_parameters(sli4_t *sli4, void *buf, size_t size)
Write a COMMON_GET_SLI4_PARAMETERS command to the provided buffer.
uint32_t uint32_t uint32_t uint32_t error_recovery_level
uint32_t check_ref_tag
Definition: ocs_hal.h:208
uint32_t buffer_address_high
Definition: sli4.h:381
static int32_t sli_skh_wqe_update_context(sli4_t *sli4, void *buf, size_t size, ocs_hal_target_login_options_t *lgn_options, uint32_t statsn)
Write an CONTEXT_UPDATE_WQE work queue entry.
int32_t sli_bmbx_command(sli4_t *sli4)
Submit a command to the bootstrap mailbox and check the status.
Definition: sli4.c:405
#define ISCSI_CQE_CODE_TCP_RECV_FIN
Definition: sli4_iscsi.h:1096
#define ocs_assert(cond,...)
Definition: ocs_debug.h:163
Scatter-Gather Entry (SGE)
Definition: sli4.h:379
static int32_t sli_skh_wqe_ini_tmf(sli4_t *sli4, void *buf, size_t size, uint16_t lun, uint32_t cmdsn, uint16_t icd_index, sli4_sge_t *sgl, uint32_t n_sge)
Write an INITIATOR_TMF WQE work queue entry.
uint32_t uint32_t uint32_t uint32_t initial_r2t
uint32_t uint32_t sge1_addr_high
uint32_t db_ring_cnt
Definition: sli4.h:2062
#define SLI4_SGE_TYPE_SKIP
Definition: sli4.h:471
uint32_t request_length
Definition: sli4.h:589
ocs_dma_t bhs
Definition: ocs_hal.h:476
Generic Command Request header.
Definition: sli4.h:582
uint32_t uint32_t sge1_addr_high
uint32_t chain_sge_init_1
Definition: sli4.h:2224
uint32_t uint32_t sge1_addr_high
uint32_t uint32_t uint32_t uint32_t uint32_t uint32_t uint32_t uint32_t uint32_t uint32_t uint32_t uint32_t rqe_count_mask
ocs_hal_dif_blk_size_e blk_size
Definition: ocs_hal.h:203
WQE used to for TGT_STS WQE (data from ini-&gt;Tgt)
uint8_t sgl_chaining_capable
Definition: sli4.h:2233
uint32_t check_guard
Definition: ocs_hal.h:208
uint32_t disable_app_ref_ffff
Definition: ocs_hal.h:208
static int32_t sli_skh_wqe_ini_nop(sli4_t *sli4, void *buf, size_t size, uint8_t dm, uint32_t cmdsn, ocs_dma_t *bhs, ocs_dma_t *payload1, ocs_dma_t *payload2, uint32_t exp_xfer_len, uint16_t icd_index)
Write an INITIATOR_NOP_OUT_COMMAND WQE work queue entry.
uint8_t wait_tcp_ack
Definition: sli4.h:2038
uint8_t t10_dif_inline_capable
Definition: sli4.h:2231
#define SLI4_WQ_DOORBELL(n, x, i)
Definition: sli4.h:271
#define SLI4_WQE_CONTEXT_UPDATE
Definition: sli4_iscsi.h:1039
ocs_session_login_options_t session_options
Definition: ocs_hal.h:322
ocs_dma_t dma
Definition: sli4.h:2048
This structure contains the fields in a CMNDINV completion.
Definition: sli4.h:1999
#define OCS_DEBUG_ENABLE_WQ_DUMP
Definition: ocs_debug.h:157
static int32_t sli_skh_wqe_tgt_datain(sli4_t *sli4, void *buf, size_t size, ocs_dma_t *bhs, uint16_t lun, uint8_t dm, uint8_t underrun, uint8_t overrun, uint32_t exp_xfer_len, uint16_t icd_index, uint16_t ref_icd_index, uint32_t data_sn, uint8_t piggy_back_status, ocs_hal_dif_info_t *dif_info, sli4_sge_t *sgl, uint32_t n_sge)
Write an TGT_DATAIN_WQE work queue entry.
WQE used to Update a connection context.