Emulex Logo
OneCoreā„¢ Storage SDK Release 11.2
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
sli4_be3_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 \defgroup sli_be3_iscsi SLI-4 BE3 iSCSI APIs
35  */
36 
37 /**
38  * @file
39  * Implementation of iSCSI BE3 SLI-4 functions
40  */
41 
42 #include "ocs.h"
43 #include "ocs_hal.h"
44 #include "sli4.h"
45 #include "sli4_iscsi.h"
46 #include "ocs_iscsi_spec.h"
47 
48 #if defined(OCS_INCLUDE_DEBUG)
49 #include "ocs_debug.h"
50 #endif
51 
52 extern const char *SLI_QNAME[];
53 
54 static int32_t sli_be3_iscsi_cqe_i_sol(sli4_t *, uint8_t *cqe,
55  sli4_qentry_fields_t *fields);
56 static int32_t sli_be3_iscsi_cqe_t_sol(sli4_t *, uint8_t *cqe,
57  sli4_qentry_fields_t *fields);
58 static int32_t sli_be3_iscsi_cqe_t_sol_data_digest(sli4_t *, uint8_t *cqe,
59  sli4_qentry_fields_t *fields);
60 static int32_t sli_be3_iscsi_cqe_t_cnxinv(sli4_t *, uint8_t *cqe,
61  sli4_qentry_fields_t *fields);
62 static int32_t sli_be3_iscsi_cqe_t_cmdinv(sli4_t *, uint8_t *cqe,
63  sli4_qentry_fields_t *fields);
64 static int32_t sli_be3_iscsi_cqe_i_t_dpdu(sli4_t *, uint8_t *cqe,
65  sli4_qentry_fields_t *fields);
66 static int32_t sli_be3_iscsi_cqe_i_t_dmsg(sli4_t *, uint8_t *cqe,
67  sli4_qentry_fields_t *fields);
68 
69 /*
70  * Determine the CQE format based on the "code" in the common format
71  */
73 {
74  sli_be3_iscsi_cqe_t_cnxinv, /* 0 dummy - should not occur */
75  sli_be3_iscsi_cqe_i_sol, /* 1 NORMAL*/
76  sli_be3_iscsi_cqe_i_sol, /* 2 CMD_DIGEST_ERROR */
77  sli_be3_iscsi_cqe_i_sol, /* 3 RECV_PDU_DSL_ERROR */
78  sli_be3_iscsi_cqe_i_sol, /* 4 RECV_SEQ_BURST_ERROR */
79  sli_be3_iscsi_cqe_i_sol, /* 5 RECV_AHS_NOT_SUPPORTED */
80  sli_be3_iscsi_cqe_i_sol, /* 6 HDR_DIGEST_ERROR */
81  sli_be3_iscsi_cqe_i_sol, /* 7 OPCODE_ERROR */
82  sli_be3_iscsi_cqe_i_sol, /* 8 ITT_TTT_WRONG_CXN */
83  sli_be3_iscsi_cqe_i_sol, /* 9 ITT_TTT_TOO_BIG */
84  sli_be3_iscsi_cqe_i_sol, /* A TCP_RECV_RST */
85  sli_be3_iscsi_cqe_i_sol, /* B TCP_TIMEOUT */
86  sli_be3_iscsi_cqe_i_sol, /* C TCP_SENT_RST */
87  sli_be3_iscsi_cqe_i_sol, /* D TCP_RECV_FIN */
88  sli_be3_iscsi_cqe_i_sol, /* E BAD_UNSOL_PDU */
89  sli_be3_iscsi_cqe_i_sol, /* F BAD_WQE_INDEX */
90  sli_be3_iscsi_cqe_i_sol, /* 10 RESIDUAL_OVERRUN */
91  sli_be3_iscsi_cqe_i_sol, /* 11 RESIDUAL_UNDERRUN */
92  sli_be3_iscsi_cqe_i_sol, /* 12 INVALID_STATSN */
93  sli_be3_iscsi_cqe_i_sol, /* 13 R2T_INVALID_FIELDS */
94  sli_be3_iscsi_cqe_i_sol, /* 14 INVALID_LUN */
95  sli_be3_iscsi_cqe_i_sol, /* 15 INVALID_ICD_STATE */
96  sli_be3_iscsi_cqe_i_sol, /* 16 RECV_PDU_INVALID_ITT */
97  sli_be3_iscsi_cqe_i_sol, /* 17 RECV_SEQ_BUF_OUT_OF_ORDER */
98  sli_be3_iscsi_cqe_i_sol, /* 18 RECV_PDU_INVALID_DATASN */
99  sli_be3_iscsi_cqe_t_cnxinv, /* 19 HOST_CXN_INVALIDATION */
100  sli_be3_iscsi_cqe_t_cnxinv, /* 1A HOST_CXN_INVL_WITH_PDU */
101  sli_be3_iscsi_cqe_t_cmdinv, /* 1B HOST_CMD_INVALIDATION */
102  sli_be3_iscsi_cqe_i_t_dpdu, /* 1C UNSOL_HDR_NOTIFY */
103  sli_be3_iscsi_cqe_i_t_dpdu, /* 1D UNSOL_DATA_NOTIFY */
104  sli_be3_iscsi_cqe_i_t_dpdu, /* 1E UNSOL_DATA_DIGEST_ERROR */
105  sli_be3_iscsi_cqe_i_t_dmsg, /* 1F TCP_ACK */
106  sli_be3_iscsi_cqe_t_cnxinv, /* 20 CMD_DATA_DIFF_CXN */
107  sli_be3_iscsi_cqe_t_cnxinv, /* 21 DIF_ERROR */
108  sli_be3_iscsi_cqe_t_cnxinv, /* 22 RECV_UNSOL_PDU_ERROR */
109  sli_be3_iscsi_cqe_t_cnxinv /* 23 dummy - should not occur */
110 };
111 
112 
114 {
115  sli_be3_iscsi_cqe_t_cnxinv, /* 0 dummy - should not occur */
116  sli_be3_iscsi_cqe_t_sol, /* 1 NORMAL*/
117  sli_be3_iscsi_cqe_t_sol_data_digest, /* 2 CMD_DIGEST_ERROR */
118  sli_be3_iscsi_cqe_t_cnxinv, /* 3 RECV_PDU_DSL_ERROR */
119  sli_be3_iscsi_cqe_t_cnxinv, /* 4 RECV_SEQ_BURST_ERROR */
120  sli_be3_iscsi_cqe_t_cnxinv, /* 5 RECV_AHS_NOT_SUPPORTED */
121  sli_be3_iscsi_cqe_t_cnxinv, /* 6 HDR_DIGEST_ERROR */
122  sli_be3_iscsi_cqe_t_cnxinv, /* 7 OPCODE_ERROR */
123  sli_be3_iscsi_cqe_t_cnxinv, /* 8 ITT_TTT_WRONG_CXN */
124  sli_be3_iscsi_cqe_t_cnxinv, /* 9 ITT_TTT_TOO_BIG */
125  sli_be3_iscsi_cqe_t_cnxinv, /* A TCP_RECV_RST */
126  sli_be3_iscsi_cqe_t_cnxinv, /* B TCP_TIMEOUT */
127  sli_be3_iscsi_cqe_t_cnxinv, /* C TCP_SENT_RST */
128  sli_be3_iscsi_cqe_t_cnxinv, /* D TCP_RECV_FIN */
129  sli_be3_iscsi_cqe_t_cnxinv, /* E BAD_UNSOL_PDU */
130  sli_be3_iscsi_cqe_t_cnxinv, /* F BAD_WQE_INDEX */
131  sli_be3_iscsi_cqe_t_cnxinv, /* 10 RESIDUAL_OVERRUN */
132  sli_be3_iscsi_cqe_t_cnxinv, /* 11 RESIDUAL_UNDERRUN */
133  sli_be3_iscsi_cqe_t_cmdinv, /* 12 INVALID_STATSN */
134  sli_be3_iscsi_cqe_t_cmdinv, /* 13 R2T_INVALID_FIELDS */
135  sli_be3_iscsi_cqe_t_cmdinv, /* 14 INVALID_LUN */
136  sli_be3_iscsi_cqe_t_cmdinv, /* 15 INVALID_ICD_STATE */
137  sli_be3_iscsi_cqe_t_cmdinv, /* 16 RECV_PDU_INVALID_ITT */
138  sli_be3_iscsi_cqe_t_cmdinv, /* 17 RECV_SEQ_BUF_OUT_OF_ORDER */
139  sli_be3_iscsi_cqe_t_cmdinv, /* 18 RECV_PDU_INVALID_DATASN */
140  sli_be3_iscsi_cqe_t_cnxinv, /* 19 HOST_CXN_INVALIDATION */
141  sli_be3_iscsi_cqe_t_cnxinv, /* 1A HOST_CXN_INVL_WITH_PDU */
142  sli_be3_iscsi_cqe_t_cmdinv, /* 1B HOST_CMD_INVALIDATION */
143  sli_be3_iscsi_cqe_i_t_dpdu, /* 1C UNSOL_HDR_NOTIFY */
144  sli_be3_iscsi_cqe_i_t_dpdu, /* 1D UNSOL_DATA_NOTIFY */
145  sli_be3_iscsi_cqe_i_t_dpdu, /* 1E UNSOL_DATA_DIGEST_ERROR */
146  sli_be3_iscsi_cqe_i_t_dmsg, /* 1F TCP_ACK */
147  sli_be3_iscsi_cqe_t_cnxinv, /* 20 CMD_DATA_DIFF_CXN */
148  sli_be3_iscsi_cqe_t_cnxinv, /* 21 DIF_ERROR */
149  sli_be3_iscsi_cqe_t_cnxinv, /* 22 RECV_UNSOL_PDU_ERROR */
150  sli_be3_iscsi_cqe_t_cnxinv /* 23 dummy - should not occur */
151 };
152 
153 /**
154  * @ingroup sli_be3_iscsi
155  * @brief Write an INITIATOR_WRITE_COMMAND WQE work queue entry.
156  *
157  * @par Description
158  * - sgl[0] - points to the BHS.
159  * - sgl[1] - must be empty.
160  * sgl[2] - starts the data SGEs.
161  *
162  * @param sli4 SLI context.
163  * @param buf Destination buffer for the WQE.
164  * @param size Buffer size in bytes.
165  * @param lun LUN value for the command.
166  * @param exp_xfer_len Total number of payload bytes.
167  * @param cmdsn The iSCSI cmdsn for the command.
168  * @param icd_index ICD index for this request.
169  * @param dif_info Pointer to the DIF fields (may be NULL).
170  * @param sgl Pointer to the SGEs for this IO.
171  * @param n_sge Number of SGEs present.
172  *
173  * @return Returns 0 on success, or a non-zero value otherwise.
174  */
175 static int32_t
176 sli_be3_wqe_ini_write(sli4_t *sli4, void *buf, size_t size,
177  uint16_t lun,
178  uint32_t exp_xfer_len,
179  uint32_t cmdsn,
180  uint16_t icd_index,
181  ocs_hal_dif_info_t* dif_info,
182  sli4_sge_t *sgl,
183  uint32_t n_sge)
184 {
185  sli4_be3_wqe_ini_write_t * req = buf;
186 
187  ocs_memset(buf, 0, size);
188 
189  req->type = SLI4_WQE_INI_WRITE;
190  req->lun = lun & 0x3fff;
191  req->dsp = (exp_xfer_len > 0 ? 1 : 0);
192  req->exp_xfer_len = exp_xfer_len;
193  req->icd_index = icd_index;
194  req->bhs_addr_high = sgl[0].buffer_address_high;
195  req->bhs_addr_low = sgl[0].buffer_address_low;
196  req->cmdsn = cmdsn;
197  if (dif_info) {
198  req->dif_mode = dif_info->dif_oper;
199  req->dif_blk_size = dif_info->blk_size;
200  }
201 
202  if (n_sge > 2) {
203  req->sge0_addr_high = sgl[2].buffer_address_high;
204  req->sge0_addr_low = sgl[2].buffer_address_low;
205  req->s0l = sgl[2].last;
206  req->sge0_offset = sgl[2].data_offset;
207  req->sge0_length = sgl[2].buffer_length;
208  }
209 
210  if (n_sge > 3) {
211  req->sge1_addr_high = sgl[3].buffer_address_high;
212  req->sge1_addr_low = sgl[3].buffer_address_low;
213  req->s1l = sgl[3].last;
214  req->sge1_offset = sgl[3].data_offset;
215  req->sge1_length = sgl[3].buffer_length;
216  }
217 
218  return 0;
219 }
220 
221 /**
222  * @ingroup sli_be3_iscsi
223  * @brief Write an INITIATOR_TMF WQE work queue entry.
224  *
225  * @par Description
226  * - sgl[0] - points to the BHS.
227  *
228  * @param sli4 SLI context.
229  * @param buf Destination buffer for the WQE.
230  * @param size Buffer size in bytes.
231  * @param lun LUN value for the command.
232  * @param cmdsn iSCSI cmdsn for the command.
233  * @param icd_index ICD index for this request.
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_be3_wqe_ini_tmf(sli4_t *sli4, void *buf, size_t size,
241  uint16_t lun,
242  uint32_t cmdsn,
243  uint16_t icd_index,
244  sli4_sge_t *sgl,
245  uint32_t n_sge)
246 {
247  sli4_be3_wqe_ini_tmf_t * req = buf;
248 
249  ocs_memset(buf, 0, size);
250 
251  req->type = SLI4_WQE_INI_TMF;
252  req->lun = lun & 0x3fff;
253  req->icd_index = icd_index;
254  req->bhs_addr_high = sgl[0].buffer_address_high;
255  req->bhs_addr_low = sgl[0].buffer_address_low;
256  req->cmdsn = cmdsn;
257 
258  return 0;
259 }
260 
261 
262 /**
263  * @ingroup sli_be3_iscsi
264  * @brief Write an INITIATOR_NOP_OUT_COMMAND WQE work queue entry.
265  *
266  * @param sli4 SLI context.
267  * @param buf Destination buffer for the WQE.
268  * @param size Buffer size in bytes.
269  * @param dm Determines whether a dmsg CQE is generated.
270  * @param cmdsn The iSCSI cmdsn for the command.
271  * @param bhs Pointer to the basic header segment.
272  * @param payload1 Optional pointer to payload memory.
273  * @param payload2 Optional pointer to payload memory.
274  * @param exp_xfer_len Total number of payload bytes.
275  * @param icd_index ICD index for this request.
276  *
277  * @return Returns 0 on success, or a non-zero value otherwise.
278  */
279 static int32_t
280 sli_be3_wqe_ini_nop(sli4_t *sli4, void *buf, size_t size,
281  uint8_t dm,
282  uint32_t cmdsn,
283  ocs_dma_t *bhs,
284  ocs_dma_t *payload1,
285  ocs_dma_t *payload2,
286  uint32_t exp_xfer_len,
287  uint16_t icd_index)
288 {
289  sli4_be3_wqe_ini_nop_t * req = buf;
290 
291  ocs_memset(buf, 0, size);
292 
293  req->type = SLI4_WQE_INI_NOP;
294  req->dsp = (exp_xfer_len > 0 ? 1 : 0);
295  req->dm = dm;
296  req->exp_xfer_len = exp_xfer_len;
297  req->icd_index = icd_index;
298  req->bhs_addr_high = ocs_addr32_hi(bhs->phys);
299  req->bhs_addr_low = ocs_addr32_lo(bhs->phys);
300  req->cmdsn = cmdsn;
301 
302  if (exp_xfer_len > 0 && payload1 != NULL) {
303  req->sge0_addr_high = ocs_addr32_hi(payload1->phys);
304  req->sge0_addr_low = ocs_addr32_lo(payload1->phys);
305  req->s0l = (payload2 == NULL ? 1 : 0);
306  req->sge0_offset = 0;
307  req->sge0_length = (payload2 != NULL ? payload1->size : exp_xfer_len);
308  }
309 
310  if (exp_xfer_len > 0 && payload1 != NULL && payload2 != NULL) {
311  req->sge1_addr_high = ocs_addr32_hi(payload2->phys);
312  req->sge1_addr_low = ocs_addr32_lo(payload2->phys);
313  req->s1l = 1;
314  req->sge1_offset = payload1->size;
315  req->sge1_length = exp_xfer_len - payload1->size;
316  }
317 
318  return 0;
319 }
320 
321 /**
322  * @ingroup sli_be3_iscsi
323  * @brief Write an INITIATOR_READ WQE work queue entry.
324  *
325  * @par Description
326  * - sgl[0] - points to the BHS.
327  * - sgl[1] - must be empty.
328  * - sgl[2] - starts the data SGEs.
329  *
330  * @param sli4 SLI context.
331  * @param buf Destination buffer for the WQE.
332  * @param size Buffer size in bytes.
333  * @param lun The LUN value for the command.
334  * @param exp_xfer_len Total number of payload bytes.
335  * @param cmdsn iSCSI cmdsn for the command.
336  * @param icd_index ICD index for this request.
337  * @param dif_info Pointer to the DIF fields (may be NULL).
338  * @param sgl Pointer to the SGEs for this IO.
339  * @param n_sge Number of SGEs present.
340  *
341  * @return Returns 0 on success, or a non-zero value otherwise.
342  */
343 static int32_t
344 sli_be3_wqe_ini_read(sli4_t *sli4, void *buf, size_t size,
345  uint16_t lun,
346  uint32_t exp_xfer_len,
347  uint32_t cmdsn,
348  uint16_t icd_index,
349  ocs_hal_dif_info_t* dif_info,
350  sli4_sge_t *sgl,
351  uint32_t n_sge)
352 {
353  sli4_be3_wqe_ini_read_t * req = buf;
354 
355  ocs_memset(buf, 0, size);
356 
357  req->type = SLI4_WQE_INI_READ;
358  req->lun = lun & 0x3fff;
359  req->exp_xfer_len = exp_xfer_len;
360  req->icd_index = icd_index;
361  req->bhs_addr_high = sgl[0].buffer_address_high;
362  req->bhs_addr_low = sgl[0].buffer_address_low;
363  req->cmdsn = cmdsn;
364  if (dif_info) {
365  req->dif_mode = dif_info->dif_oper;
366  req->dif_blk_size = dif_info->blk_size;
367  }
368 
369  if (n_sge > 2) {
370  req->sge0_addr_high = sgl[2].buffer_address_high;
371  req->sge0_addr_low = sgl[2].buffer_address_low;
372  req->s0l = sgl[2].last;
373  req->sge0_offset = sgl[2].data_offset;
374  req->sge0_length = sgl[2].buffer_length;
375  }
376 
377  if (n_sge > 3) {
378  req->sge1_addr_high = sgl[3].buffer_address_high;
379  req->sge1_addr_low = sgl[3].buffer_address_low;
380  req->s1l = sgl[3].last;
381  req->sge1_offset = sgl[3].data_offset;
382  req->sge1_length = sgl[3].buffer_length;
383  }
384 
385  return 0;
386 }
387 
388 /**
389  * @brief Write a CONTEXT_UPDATE_WQE work queue entry.
390  *
391  * @param sli4 SLI context.
392  * @param buf Destination buffer for the WQE.
393  * @param size Buffer size in bytes.
394  * @param lgn_options Target login options for the connection.
395  * @param statsn Status SN for the connection.
396  *
397  * @return Returns 0 on success, or a non-zero value otherwise.
398  */
399 static int32_t
400 sli_be3_wqe_update_context(sli4_t *sli4, void *buf, size_t size,
401  ocs_hal_target_login_options_t *lgn_options,
402  uint32_t statsn)
403 {
404  sli4_be3_wqe_context_update_t * req = buf;
405 
406  ocs_memset(buf, 0, size);
407 
409  req->dm = 1;
410  req->max_burst = lgn_options->session_options.max_burst;
411  req->max_recv_dsl = lgn_options->max_rcv_dsl;
412  req->first_burst = lgn_options->session_options.first_burst;
413  req->header_digest_enable = lgn_options->hdr_digest;
414  req->data_digest_enable = lgn_options->data_digest;
416  req->immediate_data = lgn_options->session_options.immediate_data;
417  req->initial_r2t = lgn_options->session_options.initial_r2t;
418  req->statsn = statsn;
419 
420  return 0;
421 }
422 
423 /**
424  * @ingroup sli_be3_iscsi
425  * @brief Write an TGT_STS_WQE work queue entry.
426  *
427  * @param sli4 SLI context.
428  * @param buf Destination buffer for the WQE.
429  * @param size Buffer size in bytes.
430  * @param bhs Pointer to the basic header segment.
431  * @param lun LUN value for the command.
432  * @param exp_xfer_len Total number of payload bytes.
433  * @param exp_data_sn Expected data sequence number.
434  * @param itt Initiator transfer tag.
435  * @param icd_index ICD index for this request.
436  * @param ref_icd_index Reference ICD Index.
437  * @param dif_info Pointer to the DIF fields (may be NULL).
438  * @param r2t_offset R2T buffer offset.
439  * @param sgl Pointer to the SGEs for this IO.
440  * @param n_sge Number of SGEs present.
441  *
442  * @return Returns 0 on success, or a non-zero value otherwise.
443  */
444 static int32_t
445 sli_be3_wqe_tgt_sts(sli4_t *sli4, void *buf, size_t size,
446  ocs_dma_t *bhs,
447  uint16_t lun,
448  uint32_t exp_xfer_len,
449  uint32_t exp_data_sn,
450  uint32_t itt,
451  uint16_t icd_index,
452  uint16_t ref_icd_index,
453  ocs_hal_dif_info_t* dif_info,
454  uint32_t r2t_offset,
455  sli4_sge_t *sgl,
456  uint32_t n_sge)
457 {
458  sli4_be3_wqe_tgt_sts_t * req = buf;
459 
460  ocs_memset(buf, 0, size);
461 
462  req->type = SLI4_WQE_TGT_STS;
463  req->lun = lun & 0x3fff;
464  req->exp_xfer_len = exp_xfer_len;
465  req->icd_index = icd_index;
466  req->exp_data_sn = exp_data_sn;
467  req->bhs_addr_high = ocs_addr32_hi(bhs->phys);
468  req->bhs_addr_low = ocs_addr32_lo(bhs->phys);
469  req->itt = itt;
470  req->ref_icd_index = ref_icd_index;
471  if (dif_info) {
472  req->dif_mode = dif_info->dif_oper;
473  req->dif_blk_size = dif_info->blk_size;
474  }
475  req->r2t_offset = r2t_offset;
476 
477  return 0;
478 }
479 
480 /**
481  * @ingroup sli_be3_iscsi
482  * @brief Write a TGT_DATAIN_WQE work queue entry.
483  *
484  * @par Description
485  * The SGE entries in this WQE are used if all the entries fit in the
486  * WQE for a performance increase.
487  *
488  * @param sli4 SLI context.
489  * @param buf Destination buffer for the WQE.
490  * @param size Buffer size in bytes.
491  * @param bhs Pointer to the basic header segment.
492  * @param lun The LUN value for the command.
493  * @param dm Determines whether a dmsg CQE is generated.
494  * @param underrun Sets the underrun bit in the auto response.
495  * @param overrun Sets the overrun bit in the auto response.
496  * @param exp_xfer_len Total number of payload bytes.
497  * @param icd_index ICD index fr this request.
498  * @param ref_icd_index Reference ICD Index.
499  * @param data_sn Starting data sequence number.
500  * @param piggy_back_status If true, a good status is sent to the initiator.
501  * @param dif_info Pointer to the DIF fields (may be NULL).
502  * @param sgl Pointer to the SGEs for this IO.
503  * @param n_sge Number of SGEs present.
504  *
505  * @return Returns 0 on success, or a non-zero value otherwise.
506  */
507 static int32_t
508 sli_be3_wqe_tgt_datain(sli4_t *sli4, void *buf, size_t size,
509  ocs_dma_t *bhs,
510  uint16_t lun,
511  uint8_t dm,
512  uint8_t underrun,
513  uint8_t overrun,
514  uint32_t exp_xfer_len,
515  uint16_t icd_index,
516  uint16_t ref_icd_index,
517  uint32_t data_sn,
518  uint8_t piggy_back_status,
519  ocs_hal_dif_info_t* dif_info,
520  sli4_sge_t *sgl,
521  uint32_t n_sge)
522 {
523  sli4_be3_wqe_tgt_datain_t * req = buf;
524 
525  ocs_memset(buf, 0, size);
526 
527  req->type = SLI4_WQE_TGT_DATAIN;
528  req->lun = lun & 0x3fff;
529  req->dsp = (exp_xfer_len > 0 ? 1 : 0);
530  req->dm = dm;
531  req->underrun = underrun;
532  req->overrun = overrun;
533  req->exp_xfer_len = exp_xfer_len;
534  req->icd_index = icd_index;
535  req->ref_icd_index = ref_icd_index;
536  req->data_sn = data_sn;
537  req->bhs_addr_high = ocs_addr32_hi(bhs->phys);
538  req->bhs_addr_low = ocs_addr32_lo(bhs->phys);
539  req->piggy_back_status = piggy_back_status;
540  if (dif_info) {
541  req->dif_mode = dif_info->dif_oper;
542  req->dif_blk_size = dif_info->blk_size;
543  }
544 
545  req->sge0_addr_high = sgl[0].buffer_address_high;
546  req->sge0_addr_low = sgl[0].buffer_address_low;
547  req->s0l = sgl[0].last;
548  req->sge0_offset = sgl[0].data_offset;
549  req->sge0_length = sgl[0].buffer_length;
550 
551  if (n_sge > 1) {
552  req->sge1_addr_high = sgl[1].buffer_address_high;
553  req->sge1_addr_low = sgl[1].buffer_address_low;
554  req->s1l = sgl[1].last;
555  req->sge1_offset = sgl[1].data_offset;
556  req->sge1_length = sgl[1].buffer_length;
557  }
558 
559  return 0;
560 }
561 
562 /**
563  * @ingroup sli_be3_iscsi
564  * @brief Write a TGT_SOS_WQE work queue entry.
565  *
566  * @param sli4 SLI context.
567  * @param buf Destination buffer for the WQE.
568  * @param size Buffer size in bytes.
569  * @param bhs Pointer to the basic header segment.
570  * @param payload1 Optional pointer to payload memory.
571  * @param payload2 Optional pointer to payload memory.
572  * @param lun The LUN value for the command.
573  * @param dm Determines whether a dmsg CQE is generated.
574  * @param exp_xfer_len Total # of payload bytes.
575  * @param icd_index ICD index fr this request.
576  *
577  * @return Returns 0 on success, or a non-zero value otherwise.
578  */
579 static int32_t
580 sli_be3_wqe_tgt_sos(sli4_t *sli4, void *buf, size_t size,
581  ocs_dma_t *bhs,
582  ocs_dma_t *payload1,
583  ocs_dma_t *payload2,
584  uint16_t lun,
585  uint8_t dm,
586  uint32_t exp_xfer_len,
587  uint16_t icd_index)
588 {
589  sli4_be3_wqe_tgt_sos_t * req = buf;
590 
591  ocs_memset(buf, 0, size);
592 
593  req->type = SLI4_WQE_TGT_SOS;
594  req->lun = lun & 0x3fff;
595  req->dsp = (exp_xfer_len > 0 ? 1 : 0);
596  req->dm = dm;
597  req->exp_xfer_len = exp_xfer_len;
598  req->icd_index = icd_index;
599  req->bhs_addr_high = ocs_addr32_hi(bhs->phys);
600  req->bhs_addr_low = ocs_addr32_lo(bhs->phys);
601  req->piggy_back_status = 1;
602 
603  if (exp_xfer_len > 0 && payload1 != NULL) {
604  req->sge0_addr_high = ocs_addr32_hi(payload1->phys);
605  req->sge0_addr_low = ocs_addr32_lo(payload1->phys);
606  req->s0l = (payload2 == NULL ? 1 : 0);
607  req->sge0_length = (payload2 != NULL ? payload1->size : exp_xfer_len);
608  }
609 
610  if (exp_xfer_len > 0 && payload1 != NULL && payload2 != NULL) {
611  req->sge1_addr_high = ocs_addr32_hi(payload2->phys);
612  req->sge1_addr_low = ocs_addr32_lo(payload2->phys);
613  req->s1l = 1;
614  req->sge1_length = exp_xfer_len - payload1->size;
615  }
616  return 0;
617 }
618 
619 /**
620  * @ingroup sli_be3_iscsi
621  * @brief Write an DM_CMD_WQE work queue entry.
622  *
623  * @param sli4 SLI context.
624  * @param buf Destination buffer for the WQE.
625  * @param size Buffer size in bytes.
626  * @param set_dm If TRUE, then a I_T_DMSG_CQE is generated on TCP ACK.
627  * @param incr_statsn If TRUE, the statsn is incremented by the FW.
628  * @param is_login If TRUE, the statsn is not updated by FW.
629  * @param bhs Pointer to the basic header segment.
630  * @param payload1 Optional pointer to payload memory.
631  * @param payload2 Optional pointer to payload memory.
632  * @param exp_xfer_len Total number of payload bytes.
633  * @param icd_index ICD index for this request.
634  *
635  * @return Returns 0 on success, or a non-zero value otherwise.
636  */
637 static int32_t
638 sli_be3_wqe_unassisted(sli4_t *sli4, void *buf, size_t size,
639  uint8_t set_dm,
640  uint8_t incr_statsn,
641  uint8_t is_login,
642  ocs_dma_t *bhs,
643  ocs_dma_t *payload1,
644  ocs_dma_t *payload2,
645  uint32_t exp_xfer_len,
646  uint16_t icd_index)
647 {
648  sli4_be3_wqe_unassisted_t *req = buf;
649 
650  ocs_memset(buf, 0, size);
651 
652  req->type = SLI4_WQE_UNASSISTED;
653  req->dsp = (exp_xfer_len ? 1 : 0);
654  req->dm = (set_dm ? 1 : 0);
655  req->exp_xfer_len = exp_xfer_len;
656  req->icd_index = icd_index;
657  req->login_pdu = (is_login ? 1 : 0);
658  req->bhs_addr_high = ocs_addr32_hi(bhs->phys);
659  req->bhs_addr_low = ocs_addr32_lo(bhs->phys);
660  req->piggy_back_status = incr_statsn;
661 
662  if (exp_xfer_len > 0 && payload1 != NULL) {
663  req->sge0_addr_high = ocs_addr32_hi(payload1->phys);
664  req->sge0_addr_low = ocs_addr32_lo(payload1->phys);
665  req->s0l = (payload2 == NULL ? 1 : 0);
666  req->sge0_length = (payload2 != NULL ? payload1->size : exp_xfer_len);
667  }
668 
669  if (exp_xfer_len > 0 && payload1 != NULL && payload2 != NULL) {
670  req->sge1_addr_high = ocs_addr32_hi(payload2->phys);
671  req->sge1_addr_low = ocs_addr32_lo(payload2->phys);
672  req->s1l = 1;
673  req->sge1_length = exp_xfer_len - payload1->size;
674  }
675 
676  // TODO: Revisit this
677  /* The following is based on code in be2iscsi. The HAL layer
678  * currently doesn't let us send a WQE with a type of INI_NOP_OUT.
679  * The firmware appears to have issues with sending a NOP OUT
680  * using a DM_CMD. The be2iscsi driver sends a NOP OUT as a
681  * INI_READ.
682  *
683  * This code switches a NOP OUT PDU to use a type of INI_READ,
684  * as the be2iscsi driver does. There is probably a better way
685  * to do this, but this works for now.
686  *
687  */
688  {
689  iscsi_bhs_t *hdr = bhs->virt;
690 
691  if (hdr->opcode == ISCSI_CMD_NOOP) {
692 
693  // Change the type to a IREAD
694  req->type = SLI4_WQE_INI_READ;
695  req->dm = 0;
696  }
697 
698  }
699  return 0;
700 }
701 
702 /**
703  * @ingroup sli_be3_iscsi
704  * @brief Write an WQE entry to the queue object.
705  *
706  * @param sli4 SLI context.
707  * @param q Pointer to the queue object.
708  * @param entry Pointer to the entry contents.
709  * @param io Pointer to the IO object.
710  *
711  * @return Returns 0 on success, or a non-zero value otherwise.
712  */
713 static int32_t
715  void *io)
716 {
717  int32_t rc = 0;
718  ocs_hal_io_t *hal_io = (ocs_hal_io_t*)io;
719  sli4_be3_wqe_unassisted_t *wqe = (void*)entry;
720  sli4_be3_wqe_unassisted_t *last_wqe_posted;
721  sli4_wqe_context_t *ctx;
722  uint32_t val = 0;
723 
724  ocs_lock(&q->lock);
725 
726  /* grab a free entry to see what is open */
727  ctx = ocs_list_get_head(&q->u.wq.wqe_free);
728  if (NULL != ctx) {
729  ocs_list_remove_head(&q->u.wq.wqe_free);
730  ocs_list_add_tail(&q->u.wq.wqe_busy, ctx);
731  q->u.wq.wqe_free_cnt--;
732 
733  last_wqe_posted = q->u.wq.last_wqe_posted;
734 
735  hal_io->wq_ctx = ctx;
736  ctx->io = io;
738 
739  /* Set the tcp ACK flag as required for this WQE */
740  ctx->wait_tcp_ack = wqe->dm;
741 
742  /*
743  * Note: For target STS WQE, set the TTT based on the WRB index and
744  * the icd index.
745  *
746  * Format the TTT generated by iSCSI target
747  * |-- WRB-idx (16b) --|-- zero (4b) --|-- SGL-ICD-idx (12b) --|
748  */
749  if (wqe->type == SLI4_WQE_TGT_STS) {
750  uint32_t *dword = hal_io->bhs.virt;
751 
752  hal_io->ttt = (((uint32_t)ctx->wrb_index) << 16) | hal_io->icd;
753  dword[5] = ocs_htobe32(hal_io->ttt);
754  } else if (wqe->type == SLI4_WQE_INI_WRITE ||
755  wqe->type == SLI4_WQE_INI_TMF ||
756  wqe->type == SLI4_WQE_INI_READ) {
757  uint32_t *dword = hal_io->bhs.virt;
758 
759  hal_io->itt = (((uint32_t)ctx->wrb_index) << 16) | hal_io->icd;
760  dword[4] = ocs_htobe32(hal_io->itt);
761  } else if (wqe->type == SLI4_WQE_UNASSISTED) {
762 
763  if (!ctx->wait_tcp_ack) {
764  /* DM is false, so we expect to get a I_SOL_CQE when the reply
765  * comes back. Per the SLI-4 iSCSI Command Reference, section
766  * 2.2.2.3: "For WQE operations where the response from the target
767  * is processed in a solicited manner by the SLI Port, the ITT
768  * must be set in the following manner:"
769  */
770  uint32_t *dword = hal_io->bhs.virt;
771 
772  hal_io->itt = (((uint32_t)ctx->wrb_index) << 16) | hal_io->icd;
773 
774  dword[4] = ocs_htobe32(hal_io->itt);
775 
776  }
777  }
778 
779  /* Update wrb_index and next pointer */
780  wqe->wrb_index = ctx->wrb_index;
781  wqe->next_wqe = ctx->wrb_index;
782 
783  if (last_wqe_posted != NULL) {
784  last_wqe_posted->next_wqe = ctx->wrb_index;
785  }
786 
787 #if defined(OCS_INCLUDE_DEBUG)
788  {
789  char desc[32];
790 
791  snprintf(desc, sizeof(desc), "%s entry %d", q->name, ctx->wrb_index);
792  ocs_dump32(OCS_DEBUG_ENABLE_WQ_DUMP, sli4->os, desc, entry, q->size);
793 
794  // For any WQE type other than CONTEXT_UPDATE also dump the BHS
796  hal_io->bhs.virt, sizeof(iscsi_login_cmd_hdr_t));
797  }
798 
799 #endif
800  ocs_memcpy(ctx->qe, entry, q->size);
801  q->index = ctx->wrb_index; /* Needed for dump_queue */
802  q->n_posted = 1;
803  q->u.wq.last_wqe_posted = ctx->qe;
804 
805  ocs_dma_sync(&q->dma, OCS_DMASYNC_PREWRITE);
806 
807  val = SLI4_WQ_DOORBELL(q->n_posted, ctx->wrb_index, q->id);
809  q->n_posted = 0;
810  } else {
811  rc = -1;
812  ocs_log_err(sli4->os, "failed to allocate a WQE object\n");
813  }
814 
815  ocs_unlock(&q->lock);
816 
817  return rc;
818 }
819 
820 /**
821  * @ingroup sli_be3_iscsi
822  * @brief Writes a 1 to the invalidate bit of the WQE.
823  *
824  * @param sli4 SLI context.
825  * @param q Pointer to queue object.
826  * @param io Pointer to the IO object.
827  * @param is_for_tm TRUE if the IO is being aborted for task management,
828  * otherwise FALSE.
829  *
830  * @return Returns 0 on success, or a non-zero value otherwise.
831  */
832 static int32_t
834  uint8_t is_for_tm)
835 {
836  int32_t rc = -1;
838  sli4_wqe_context_t *ctx;
839 
840  /* No clean way to do this excpet to walk the active WQEs */
841  ocs_lock(&q->lock);
842  ctx = ocs_list_get_head(&q->u.wq.wqe_busy);
843  while (NULL != ctx) {
844  if (ctx->io == io) {
845  wqe = (sli4_be3_wqe_unassisted_t *)ctx->qe;
846  wqe->inv = 1;
847  rc = 0;
848 
849  /*
850  * If this is for Task management, then we must wait
851  * for the TCP_ACK before issuing a completion for this
852  * io, otherwise the FW may still be using it.
853  */
855  ctx->wait_tcp_ack = is_for_tm;
856  break;
857  }
858  ctx = ocs_list_next(&q->u.wq.wqe_busy, ctx);
859  }
860 
861  ocs_unlock(&q->lock);
862 
863  return rc;
864 }
865 
866 /**
867  * @brief Parse an iSCSI work queue CQ entry.
868  *
869  * @param sli4 SLI context.
870  * @param cqe Pointer to the CQ entry.
871  * @param fields Returns the fields embedded in the CQ entry.
872  *
873  * @return Returns 0 on success, or a non-zero value otherwise.
874  */
875 static int32_t sli_be3_iscsi_cqe_i_sol(sli4_t *sli4, uint8_t *cqe,
876  sli4_qentry_fields_t *fields)
877 {
879 
880  fields->ctype = SLI_CQENTRY_INI_IO;
881 
882  fields->msg.isol.residual_cnt =
884  i_sol->code == ISCSI_CQE_CODE_RESIDUAL_UNDERRUN) ? i_sol->residual : 0);
885  fields->msg.isol.exp_cmdsn = i_sol->expcmdsn;
886  fields->msg.isol.cid = i_sol->cid;
887  fields->msg.isol.hw_status = i_sol->hw_sts;
888  fields->msg.isol.status = i_sol->status;
889  fields->msg.isol.response = i_sol->response;
890  fields->msg.isol.flags = i_sol->flags;
891  fields->msg.isol.wqe_index = i_sol->wqe_index;
892  fields->msg.isol.cmd_window = i_sol->cmd_window;
893  fields->msg.isol.code = i_sol->code;
894 
895  if (i_sol->code != ISCSI_CQE_CODE_NORMAL &&
898  i_sol->code != ISCSI_CQE_CODE_TCP_RECV_FIN) {
899  ocs_log_test(sli4->os, "WQ Error: status 0x%02x\n", i_sol->code);
900  ocs_dump32(OCS_DEBUG_ALWAYS, sli4->os, "cqe", cqe,
902  }
903  i_sol->valid = 0;
904  return 0;
905 }
906 
907 /**
908  * @brief Parse a iSCSI work queue CQ entry.
909  *
910  * @param sli4 SLI context.
911  * @param cqe Pointer to the CQ entry.
912  * @param fields Returns the fields embedded in the CQ entry.
913  *
914  * @return Returns 0 on success, or a non-zero value otherwise.
915  */
916 static int32_t sli_be3_iscsi_cqe_t_sol(sli4_t *sli4, uint8_t *cqe,
917  sli4_qentry_fields_t *fields)
918 {
920 
921  fields->ctype = SLI_CQENTRY_TGT_IO;
922 
923  fields->msg.tsol.hw_status = t_sol->hw_sts;
924  fields->msg.tsol.cid = t_sol->cid;
925  fields->msg.tsol.wqe_index = t_sol->wqe_index;
926  fields->msg.tsol.code = t_sol->code;
927 
928  if (t_sol->code != ISCSI_CQE_CODE_NORMAL) {
929  ocs_log_test(sli4->os, "WQ Error: status 0x%02x\n", t_sol->code);
930  ocs_dump32(OCS_DEBUG_ALWAYS, sli4->os, "cqe", cqe,
932  }
933  t_sol->valid = 0;
934  return 0;
935 }
936 
937 /**
938  * @brief Parse a iSCSI work queue CQ entry.
939  *
940  * @param sli4 SLI context.
941  * @param cqe Pointer to the CQ entry.
942  * @param fields Returns the fields embedded in the CQ entry.
943  *
944  * @return Returns 0 on success, or a non-zero value otherwise.
945  */
946 static int32_t sli_be3_iscsi_cqe_t_sol_data_digest(sli4_t *sli4, uint8_t *cqe,
947  sli4_qentry_fields_t *fields)
948 {
949  sli4_be3_iscsi_t_sol_data_digest_cqe_t * msg = (void*)cqe;
951 
953 
954  digest->buffer_offset = msg->buffer_offset;
955  digest->exp_statsn = msg->exp_statsn;
956  digest->cid = msg->cid;
957  digest->datasn = msg->datasn;
958  digest->fin = msg->fin;
959  digest->data_seg_length = msg->data_seg_len;
960  digest->icd_index = msg->sgl_icd_index;
961 
962  ocs_log_test(sli4->os, "WQ Error: status 0x%02x\n", msg->code);
963  ocs_dump32(OCS_DEBUG_ALWAYS, sli4->os, "cqe", cqe,
965  msg->valid = 0;
966  return 0;
967 }
968 
969 
970 /**
971  * @brief Parse a iSCSI work queue CQ entry.
972  *
973  * @param sli4 SLI context.
974  * @param cqe Pointer to the CQ entry.
975  * @param fields Returns the fields embedded in the CQ entry.
976  *
977  * @return Returns 0 on success, or a non-zero value otherwise.
978  */
979 static int32_t sli_be3_iscsi_cqe_t_cnxinv(sli4_t *sli4, uint8_t *cqe,
980  sli4_qentry_fields_t *fields)
981 {
982  sli4_be3_iscsi_t_cnxinv_cqe_t *msg = (void*)cqe;
983  sli4_qentry_fields_cnxinv_t *cnxinv = &fields->msg.cnxinv;
984 
985  fields->ctype = SLI_CQENTRY_CNX_INVALID;
986 
987  cnxinv->addr_high = msg->def_buf_addr_high;
988  cnxinv->addr_low = msg->def_buf_addr_low;
989  cnxinv->partial_data_length = msg->partial_dsl;
990  cnxinv->cid = msg->cid;
991  cnxinv->rq_index = msg->rq_index;
992  cnxinv->code = msg->code;
993 
994  /* Mask normal things or the DVT group gets excited */
995  if (cnxinv->code != ISCSI_CQE_CODE_TCP_RECV_FIN &&
996  cnxinv->code != ISCSI_CQE_CODE_TCP_RECV_RST &&
999  ocs_log_test(sli4->os, "WQ Error: status 0x%02x\n", msg->code);
1000  ocs_dump32(OCS_DEBUG_ALWAYS, sli4->os, "cqe", cqe,
1002  }
1003  msg->valid = 0;
1004  return 0;
1005 }
1006 
1007 
1008 /**
1009  * @brief Parse a iSCSI work queue CQ entry.
1010  *
1011  * @param sli4 SLI context.
1012  * @param cqe Pointer to the CQ entry.
1013  * @param fields Returns the fields embedded in the CQ entry.
1014  *
1015  * @return Returns 0 on success, or a non-zero value otherwise.
1016  */
1017 static int32_t sli_be3_iscsi_cqe_t_cmdinv(sli4_t *sli4, uint8_t *cqe,
1018  sli4_qentry_fields_t *fields)
1019 {
1020  sli4_be3_iscsi_t_cmndinv_cqe_t *msg = (void*)cqe;
1021  sli4_qentry_fields_tcmdinv_t *cmdinv = &fields->msg.tcmdinv;
1022 
1024 
1025  cmdinv->cid = msg->cid;
1026  cmdinv->icd_index = msg->sgl_icd_index;
1027  cmdinv->code = msg->code;
1028 
1029  ocs_log_test(sli4->os, "WQ Error: status 0x%02x\n", msg->code);
1030  ocs_dump32(OCS_DEBUG_ALWAYS, sli4->os, "cqe", cqe,
1032  msg->valid = 0;
1033  return 0;
1034 }
1035 
1036 
1037 /**
1038  * @brief Parse an iSCSI work queue CQ entry.
1039  *
1040  * @param sli4 SLI context.
1041  * @param cqe Pointer to the CQ entry.
1042  * @param fields Returns the fields embedded in the CQ entry.
1043  *
1044  * @return Returns 0 on success, or a non-zero value otherwise.
1045  */
1046 static int32_t sli_be3_iscsi_cqe_i_t_dpdu(sli4_t *sli4, uint8_t *cqe,
1047  sli4_qentry_fields_t *fields)
1048 {
1049  sli4_be3_iscsi_i_t_dpdu_cqe_t *msg = (void*)cqe;
1050  sli4_qentry_fields_dpdu_t *dpdu = &fields->msg.dpdu;
1051 
1052  fields->ctype = SLI_CQENTRY_RQ;
1053  dpdu->code = msg->code;
1054  dpdu->addr_high = msg->def_buf_addr_high;
1055  dpdu->addr_low = msg->def_buf_addr_low;
1056  dpdu->data_length = msg->data_length;
1057  dpdu->cid = msg->cid;
1058  dpdu->rq_index = msg->rq_index;
1059  dpdu->final = msg->fin;
1060 
1061  return 0;
1062 }
1063 
1064 
1065 /**
1066  * @brief Parse a iSCSI work queue CQ entry.
1067  *
1068  * @param sli4 SLI context.
1069  * @param cqe Pointer to the CQ entry.
1070  * @param fields Returns the fields embedded in the CQ entry.
1071  *
1072  * @return Returns 0 on success, or a non-zero value otherwise.
1073  */
1074 static int32_t sli_be3_iscsi_cqe_i_t_dmsg(sli4_t *sli4, uint8_t *cqe,
1075  sli4_qentry_fields_t *fields)
1076 {
1077  sli4_be3_iscsi_i_t_dmsg_cqe_t *msg = (void*)cqe;
1078  sli4_qentry_fields_dmsg_t *dmsg = &fields->msg.dmsg;
1079 
1080  fields->ctype = SLI_CQENTRY_TCP_ACK;
1081 
1082  dmsg->cid = msg->cid;
1083  dmsg->wqe_index = msg->wqe_index;
1084  dmsg->code = msg->code;
1085 
1086  return 0;
1087 }
1088 
1089 /**
1090  * @brief Note: GET_SLI4_PARAMETERS IOCTL is not supported on BE3, so we just
1091  * return constant values.
1092  *
1093  * @param sli4 SLI context.
1094  *
1095  * @return Returns 0 on success, or a non-zero value otherwise.
1096  */
1097 int32_t
1099 {
1100  sli4->config.max_qentries[SLI_QTYPE_EQ] = 1024;
1101  sli4->config.max_qentries[SLI_QTYPE_CQ] = 1024;
1102  sli4->config.max_qentries[SLI_QTYPE_MQ] = 128;
1103  sli4->config.max_qentries[SLI_QTYPE_WQ] = 128;
1104  sli4->config.max_qentries[SLI_QTYPE_RQ] = 512;
1105  sli4->config.sge_supported_length = 65536;
1106 
1107  return 0;
1108 }
1109 
1112  .wqe_ini_read = sli_be3_wqe_ini_read,
1113  .wqe_ini_write = sli_be3_wqe_ini_write,
1114  .wqe_ini_nop = sli_be3_wqe_ini_nop,
1115  .wqe_ini_tmf = sli_be3_wqe_ini_tmf,
1116  .wqe_tgt_datain = sli_be3_wqe_tgt_datain,
1117  .wqe_tgt_sts = sli_be3_wqe_tgt_sts,
1118  .wqe_tgt_sos = sli_be3_wqe_tgt_sos,
1119  .wqe_unassisted = sli_be3_wqe_unassisted,
1120  .queue_iscsi_wq_write = sli_be3_queue_iscsi_wq_write,
1121  .queue_iscsi_wqe_invalidate = sli_be3_queue_iscsi_wqe_invalidate
1122 };
1123 
1124 /* vim: set noexpandtab textwidth=120: */
This structure contains the type and associated fields for a CQE completion.
Definition: sli4.h:2017
static int32_t sli_be3_wqe_update_context(sli4_t *sli4, void *buf, size_t size, ocs_hal_target_login_options_t *lgn_options, uint32_t statsn)
Write a CONTEXT_UPDATE_WQE work queue entry.
#define SLI4_WQE_INI_NOP
Definition: sli4_iscsi.h:1037
ocs_os_handle_t os
Definition: sli4.h:2202
uint32_t buffer_length
Definition: sli4.h:386
#define ISCSI_CQE_CODE_MAX
Definition: sli4_iscsi.h:1119
Used to decode CMNDINV CQEs.
sli4_wqe_context_t * wq_ctx
Definition: ocs_hal.h:495
WQE used to for INITIATOR_NOP_OUT WQE (data from ini-&gt;Tgt)
static int32_t sli_be3_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.
uint32_t uint32_t uint32_t statsn
static int32_t sli_be3_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.
int32_t cqe_handler_t(sli4_t *, uint8_t *cqe, sli4_qentry_fields_t *fields)
Definition: sli4_iscsi.h:1279
Used to decode CNXINV CQEs.
uint32_t data_offset
Definition: sli4.h:383
uint32_t uint32_t sge1_addr_high
cqe_handler_t * ini_be3_cqe_handlers[ISCSI_CQE_CODE_MAX+1]
uint16_t size
Definition: sli4.h:2051
#define SLI4_WQE_INI_READ
Definition: sli4_iscsi.h:1038
uint32_t uint32_t sge1_addr_high
uint32_t max_qentries[SLI_QTYPE_MAX]
Definition: sli4.h:2240
static int32_t sli_be3_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 * qe
Definition: sli4.h:2036
Defines the generic iSCSI basic header segment.
This structure contains the fields in a DMSG completion.
Definition: sli4.h:1965
static int32_t sli_be3_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.
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
static int32_t sli_be3_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.
static int32_t sli_be3_iscsi_cqe_t_sol(sli4_t *, uint8_t *cqe, sli4_qentry_fields_t *fields)
Parse a iSCSI work queue CQ entry.
WQE used to Update a connection context.
static void * ocs_list_get_head(ocs_list_t *list)
Return the first item in the list.
Definition: ocs_list.h:292
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
union sli4_qentry_fields_t::@32 msg
sli4_qentry_e ctype
Definition: sli4.h:2018
uint32_t index
Definition: sli4.h:2050
cqe_handler_t * tgt_be3_cqe_handlers[ISCSI_CQE_CODE_MAX+1]
uint32_t uint32_t wqe_index
#define SLI4_WQE_UNASSISTED
Definition: sli4_iscsi.h:1043
uint32_t itt
Definition: ocs_hal.h:491
#define ISCSI_CQE_CODE_HOST_CXN_INVL_WITH_PDU
Definition: sli4_iscsi.h:1109
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
static int32_t sli_be3_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.
uint32_t uint32_t icd_index
Used to decode T_SOL CQEs.
sli_wqe_handlers_t sli_be3_iscsi_wqe_handlers
sli4_qentry_fields_tsol_t tsol
Definition: sli4.h:2022
#define ISCSI_CQE_CODE_TCP_RECV_RST
Definition: sli4_iscsi.h:1093
#define ISCSI_CQE_CODE_HOST_CXN_INVALIDATION
Definition: sli4_iscsi.h:1108
#define OCS_DEBUG_ALWAYS
Definition: ocs_debug.h:154
uint32_t ttt
Definition: ocs_hal.h:492
static int32_t sli_be3_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.
union sli4_queue_t::@33 u
#define SLI4_WQE_TGT_STS
Definition: sli4_iscsi.h:1040
Definition: sli4.h:2201
ocs_lock_t lock
Definition: sli4.h:2049
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
static int32_t sli_be3_iscsi_cqe_i_t_dpdu(sli4_t *, uint8_t *cqe, sli4_qentry_fields_t *fields)
Parse an iSCSI work queue CQ entry.
static int32_t sli_be3_iscsi_cqe_i_sol(sli4_t *, uint8_t *cqe, sli4_qentry_fields_t *fields)
Parse an iSCSI work queue CQ entry.
uint32_t uint32_t sge1_addr_high
uint32_t uint32_t data_digest_enable
void ocs_swap_and_dump32(uint32_t mask, ocs_os_handle_t os, const char *label, void *buf, uint32_t buf_length)
Definition: ocs_debug.c:196
WQE used to transmit a PDU without any modificiation.
uint32_t uint32_t immediate_data
#define ISCSI_CMD_NOOP
static int32_t sli_be3_iscsi_cqe_t_cnxinv(sli4_t *, uint8_t *cqe, sli4_qentry_fields_t *fields)
Parse a iSCSI work queue CQ entry.
const char * SLI_QNAME[]
Definition: sli4.c:75
WQE used to for INITIATOR_READ WQE (data from ini-&gt;Tgt)
sli4_qentry_fields_isol_t isol
Definition: sli4.h:2021
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
static int32_t sli_be3_queue_iscsi_wq_write(sli4_t *sli4, sli4_queue_t *q, uint8_t *entry, void *io)
Write an WQE entry to the queue object.
This structure contains the fields in a T_DATA_DIGEST completion.
Definition: sli4.h:1974
uint16_t id
Definition: sli4.h:2054
uint32_t uint32_t sge1_addr_high
This structure contains the fields in a CNXINV completion.
Definition: sli4.h:1987
#define ISCSI_CQE_CODE_RESIDUAL_OVERRUN
Definition: sli4_iscsi.h:1099
sli4_qentry_fields_cnxinv_t cnxinv
Definition: sli4.h:2025
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
#define SLI4_WQE_INI_TMF
Definition: sli4_iscsi.h:1036
WQE used to for TGT_SOS WQE (Tgt Response)
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
uint32_t opcode
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 uint32_t sge1_addr_high
ocs_hal_dif_oper_e dif_oper
Definition: ocs_hal.h:202
This structure is used to track the SLI4 queues.
Definition: sli4.h:2046
#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
WQE used to for TGT_STS WQE (data from Tgt-&gt;Ini)
void sli_reg_write(sli4_t *sli, sli4_regname_e reg, uint32_t val)
Write the value to the given SLI register.
Definition: sli4.c:234
uint32_t uint32_t sge1_addr_high
uint32_t buffer_address_low
Definition: sli4.h:382
static void * ocs_list_next(ocs_list_t *list, void *item)
Get the next item on the list.
Definition: ocs_list.h:339
#define SLI4_WQE_INI_WRITE
Definition: sli4_iscsi.h:1035
uint32_t uint32_t header_digest_enable
Used to decode I_SOL CQEs.
#define ISCSI_CQE_CODE_NORMAL
Definition: sli4_iscsi.h:1084
sli4_qentry_fields_dmsg_t dmsg
Definition: sli4.h:2023
uint32_t uint32_t exp_data_sn
static int32_t sli_be3_iscsi_cqe_i_t_dmsg(sli4_t *, uint8_t *cqe, sli4_qentry_fields_t *fields)
Parse a iSCSI work queue CQ entry.
This structure contains the fields in a DPDU completion.
Definition: sli4.h:1926
WQE used to for TGT_STS WQE (data from ini-&gt;Tgt)
uint32_t last
Definition: sli4.h:383
uint32_t buffer_address_high
Definition: sli4.h:381
int32_t sli_be3_get_sli4_parameters(sli4_t *sli4)
Note: GET_SLI4_PARAMETERS IOCTL is not supported on BE3, so we just return constant values...
#define ISCSI_CQE_CODE_TCP_RECV_FIN
Definition: sli4_iscsi.h:1096
static int32_t sli_be3_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 a TGT_DATAIN_WQE work queue entry.
uint32_t uint32_t data_sn
Scatter-Gather Entry (SGE)
Definition: sli4.h:379
WQE used to for INITIATOR_WRITE_COMMAND WQE (data from ini-&gt;Tgt)
static int32_t sli_be3_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 a TGT_SOS_WQE work queue entry.
static int32_t sli_be3_iscsi_cqe_t_sol_data_digest(sli4_t *, uint8_t *cqe, sli4_qentry_fields_t *fields)
Parse a iSCSI work queue CQ entry.
WQE used to for INITIATOR_TMF WQE.
uint32_t uint32_t ref_icd_index
ocs_dma_t bhs
Definition: ocs_hal.h:476
Used to decode DPDU CQEs.
ocs_hal_dif_blk_size_e blk_size
Definition: ocs_hal.h:203
Used to decode DMSG CQEs.
uint8_t wait_tcp_ack
Definition: sli4.h:2038
#define SLI4_WQ_DOORBELL(n, x, i)
Definition: sli4.h:271
#define SLI4_WQE_CONTEXT_UPDATE
Definition: sli4_iscsi.h:1039
uint32_t uint32_t max_recv_dsl
ocs_session_login_options_t session_options
Definition: ocs_hal.h:322
static int32_t sli_be3_iscsi_cqe_t_cmdinv(sli4_t *, uint8_t *cqe, sli4_qentry_fields_t *fields)
Parse a iSCSI work queue CQ entry.
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
Defines the iSCSI login PDU header.
uint32_t uint32_t error_recovery_level
Used to decode T_SOL_DATA_DIGEST CQEs.